Query a M2M related field in Django - django

I have a Model Return in my projects like the following:
class Kit(models.Model):
kit_name = models.CharField(max_length=500, default=0)
kit_info = models.CharField(max_length=500, default=0)
kit_client = models.ForeignKey(Client, on_delete=models.CASCADE)
class ReturnKits(models.Model):
kit = models.ForeignKey(Kit, on_delete=models.CASCADE)
quantity = models.IntegerField(default=0)
items = models.ManyToManyField(ReturnKitsProducts)
class Return(models.Model):
transaction_date = models.DateTimeField(default=datetime.now)
transaction_no = models.IntegerField(default=0, blank=True, null=True)
is_delivered = models.BooleanField(default=False)
kits = models.ManyToManyField(ReturnKits)
How can I select all the Return objects which contains the kit with kit_client = 4?
I know we can query directly related objects using __ but how to query nested ones ?

You can continue traversing the relationships with continued __ segments.
Return.objects.filter(kits__kit__kit_client=4)

Related

How to use django-autocomplete-light and django-hacker to make a chained dropdown in django admin?

I have 3 models 1) university 2) courses and 3) enquiry.
My enquiry model has a foreign key to "course". And Course has a foreign key to the university. I only want to show the courses related to that university while adding an enquiry. I tried django-smart-select but failed to do so. I tried This answer but I dont understand the logic and failed to implement in my project.
this is my models.py file
class university(models.Model):
univ_name = models.CharField(max_length=100)
country = CountryField(blank=True, null=True)
univ_desc = models.CharField(max_length=1000)
univ_logo = models.ImageField(upload_to="media")
univ_phone = models.CharField(max_length=10, blank=True)
univ_email = models.EmailField(max_length=254, blank=True)
univ_website = models.URLField(blank=True)
assigned_users = models.ForeignKey(get_user_model(), on_delete=models.CASCADE, default="")
def __str__(self):
return self.univ_name
class Meta:
verbose_name_plural = "Universities"
class Course(models.Model):
university = models.ForeignKey(university, on_delete=models.CASCADE)
course_name = models.CharField(max_length=100)
course_levels = models.ForeignKey(course_levels, on_delete=models.CASCADE)
intake = models.ForeignKey(intake, on_delete=models.CASCADE)
documents_required = models.ForeignKey(documents_required, on_delete=models.CASCADE)
course_requirements = models.ForeignKey(course_requirements, on_delete=models.CASCADE)
Active = models.BooleanField()
def __str__(self):
return self.course_name
class enquiry(models.Model):
student_name = models.CharField(max_length=100)
student_phone = models.CharField(max_length=10)
student_email = models.EmailField()
student_address = models.TextField()
current_education = models.ForeignKey(current_education, on_delete=models.CASCADE)
country_interested = CountryField(blank=True, null=True)
university_interested = models.ForeignKey(university, on_delete=models.CASCADE)
course_interested = models.ForeignKey(Course, on_delete=models.CASCADE, limit_choices_to={'Active':True})
level_applying_for = models.ForeignKey(course_levels, on_delete=models.CASCADE)
intake_interested = models.ForeignKey(intake, on_delete=models.CASCADE)
assigned_users = models.ForeignKey(User, on_delete=models.CASCADE, default="", limit_choices_to={"is_active": True})
enquiry_status = models.ForeignKey(enquiry_status, on_delete=models.CASCADE, default="")
course_interested= ChainedForeignKey(Course,chained_field= 'university_interested',chained_model_field= 'university',show_all= False,auto_choose= True,sort=True,limit_choices_to = {"Active": True},)
I want to show the course_interested field related to that university. Need help.
I tried using django-smart-select but failed to implement it. I am not aware of jquery and ajax so that is out of the question to use in my project.
got the solution I used the django-select2 and was able to solve this issue.

Django: handle multi stock (related table) in Product Based List View

I need to manage Products shared by multiple Warehouses.
I tried to get through with annotate, prefetch_related, select_related but in my case, those solutions are upside-down for my need. I need first to get product and then, the related stock in each warehouse and display it in template and the foreignKey is in my Sststock, not in Product
I have :
Product models.py
class Product(models.Model):
famille = models.ForeignKey(Famille, on_delete=SET_NULL, null=True)
sku = models.CharField(max_length=100, unique=True)
nom = models.CharField(max_length=250)
fournisseur = models.ForeignKey(
Supplier, on_delete=models.SET_NULL, default=12, null=True)
qty = models.IntegerField()
mini = models.IntegerField()
maxi = models.IntegerField()
[...]
Warehouse models.py
class Warehouse(models.Model):
nom = models.CharField(max_length=100)
code = models.CharField(max_length=10, null=True)
adresse = models.CharField(max_length=255)
cp = models.IntegerField()
ville = models.CharField(max_length=50)
tel = models.CharField(max_length=10)
email = models.EmailField(default='sav#iturbo.fr', null=False, blank=False)
allow_store = models.BooleanField(default=False)
def __str__(self):
return self.nom.upper()
Sststock models.py
class SstStock(models.Model):
sst = models.ForeignKey(Warehouse, on_delete=models.CASCADE)
mageid = models.ForeignKey(Product, on_delete=models.CASCADE, null=True)
qty = models.IntegerField()
last_update = models.DateTimeField(default=timezone.now)
For the time, I only have 3 warehouses but there could have more in the future.
First I had "hard-coded" my 3 warehouses in Product's model but this solution was not easily scalable.
What would be the best way to achieve my goal ?
I've seen solution with Mysql Stored Procedures in PhpMyAdmin for creating innerJoin tables but there is maybe possibilities within Django.

How to add ArrayField in Django?

my models.py
class LiveClass_details(models.Model):
standard = models.ForeignKey(LiveClass, on_delete=models.CASCADE)
chapter_details = models.TextField(default='')
mentor_id = models.ForeignKey(Mentor, max_length=30, on_delete=models.CASCADE)
start_time = models.DateTimeField()
end_time = models.DateTimeField()
doubtClass = models.OneToOneField(DoubtClasses, on_delete=models.PROTECT, null=True, blank=True)
isDraft = models.BooleanField(default=True)
ratings = models.FloatField(default=0)
no_of_students_registered = models.IntegerField(default=0)
# registered_students = models.ManyToManyField(RegisteredNames, null=True, blank=True)
no_of_students_attended = models.IntegerField(default=0)
class Meta:
verbose_name_plural = 'LiveClass_details'
class RegisteredNames(models.Model):
name = models.CharField(max_length=100, unique=True)
liveclass_id = models.ForeignKey
I am creating a endpoint where when a user register himself his name will get added to registered_students , so i had made a registered students ManyToMany Field hoping it will get updated when a user is registered but then i understand that it will contain all the names that are present in the RegisteredNames Model meaning names registered across all the liveclasses but i want only the names that are registered for a particular liveclass in the field so i need a array like field which i think is not possible so please help me in improving my logic, how can i achieve it
The documentation and django tutorials are very good: https://docs.djangoproject.com/en/3.2/topics/db/models/ https://docs.djangoproject.com/en/3.2/intro/tutorial02/#creating-models
Your code is very close. You don’t need the many-to-many field, and you need to specify the type of the Foreign key relationship in the RegisteredNames. You can do this:
class LiveClass_details(models.Model):
standard = models.ForeignKey(LiveClass, on_delete=models.CASCADE)
chapter_details = models.TextField(default='')
mentor_id = models.ForeignKey(Mentor, max_length=30, on_delete=models.CASCADE)
start_time = models.DateTimeField()
end_time = models.DateTimeField()
doubtClass = models.OneToOneField(DoubtClasses, on_delete=models.PROTECT, null=True, blank=True)
isDraft = models.BooleanField(default=True)
ratings = models.FloatField(default=0)
no_of_students_attended = models.IntegerField(default=0)
class Meta:
verbose_name_plural = 'LiveClass_details'
class RegisteredNames(models.Model):
name = models.CharField(max_length=100, unique=True)
liveclass = models.ForeignKey(LiveClass_details, on_delete=Models.CASCADE)
Then, simply:
name = RegisteredNames.objects.create(name="Dhruv", liveclass_id=1)
To get all the registered names from a liveclass_details:
names = LiveClass_details.objects.get(id=1).registerednames_set.all()
num_reg = len(names)

Django model managers -object is not callable

First time I am using the managers in django model so problem can be very basic
I try to calculate totals for my Materials model
those totals are stored in different tables like Inventory , PO, SO
For this reason I decided to do the aggregations inside Material model manager
class MaterialInventoryManager(models.Manager):
def total_active_inventory(self):
return self.get_query_set().annotate(total_inventory=Sum('inventory__quantity')).filter(is_active = True)
class Material(models.Model):
version = IntegerVersionField( )
code = models.CharField(max_length=30)
name = models.CharField(max_length=30)
description = models.TextField(null=True, blank=True)
materialuom = models.CharField(max_length=1,
choices=UOM_CHOICES)
creation_time = models.DateTimeField(auto_now_add=True, blank=True)
total_inventory = MaterialInventoryManager()
objects = MaterialInventoryManager()
#with_author
class Inventory(models.Model):
material = models.OneToOneField('item.Material',null=True, blank=True)
# material_UOM = models.OneToOneField('item.UOM_BINUOM',null=True, blank=True)
warehouse_Bin = models.ForeignKey(WarehouseBin)
is_active = models.BooleanField(default=True)
quantity = models.DecimalField(max_digits=8, decimal_places=5)
creation_time = models.DateTimeField(auto_now_add=True, blank=True)
And when I execute from shell Material.total_inventory()
I am getting
What I am doing wrong?
You have typo, it's self.get_queryset() not self.get_query_set().
Django doc about get_queryset().

django many to many field - programmatically retrieve relations

I have been working on a model for tags and am trying to avoid using contenttypes. I have couple questions related to ManyToManyField in django.
I have the following model
taggables/models.py
class Tag(models.Model):
tag_statuses = (
(u'P', _('Pending approval')),
(u'A', _('Approved')),
)
slug = models.SlugField()
created_at = models.DateTimeField(null=True, blank=True)
created_by = models.ForeignKey(User, related_name='tagged_item_created_by')
status = models.CharField(max_length=20, choices=tag_statuses)
site = models.ForeignKey(Site, default=settings.SITE_ID, related_name='tagged_item_site')
def __unicode__(self):
return self.slug
class TagI18n(models.Model):
tag = models.CharField(max_length=100)
descriptor = models.TextField(null=True, blank=True)
# i18n properties
item = models.ForeignKey(Tag)
language = models.CharField(max_length=6, choices=settings.LANGUAGES, default=settings.LANGUAGE_CODE)
class Meta:
unique_together = (("language", "item"))
def __unicode__(self):
return self.tag
I also have different apps around my project that uses tag model as many to many field. such as events for example
evetns/models.py
class Item(models.Model):
event_status_list = (
(u'P', _('Pending approval')),
(u'A', _('Approved')),
(u'R', _('Rejected')),
(u'S', _('Spam')),
)
published_at = models.DateTimeField(null=True, blank=True)
published_by = models.ForeignKey(User, null=True, blank=True, related_name='item_published_by')
updated_by = models.ForeignKey(User, null=True, blank=True, related_name='item_updated_by')
updated_at = models.DateTimeField(null=True, blank=True)
site = models.ForeignKey(Site, default=settings.SITE_ID, related_name='events_item_site')
event_slug = models.SlugField(null=True, blank=True)
# event timing
event_start_date = models.DateField()
event_start_time = models.TimeField(null=True, blank=True)
event_end_date = models.DateField()
event_end_time = models.TimeField(null=True, blank=True)
event_recurrent = models.BooleanField(default=False)
event_status = models.CharField(max_length=20, choices=event_status_list, default=u'P')
# relations
media = models.ManyToManyField(ImageFile, null=True, blank=True)
comments = models.ManyToManyField(Comment, null=True, blank=True)
votes = models.ManyToManyField(Vote, null=True, blank=True)
tags = models.ManyToManyField(Tag, null=True, blank=True)
audience = models.ManyToManyField(Audience, null=True, blank=True)
Now what am trying to do here is run a query to programmatically retrieve all the related models to Tag and then count how many a times a tag was used. Am sure I can do that with contenttypes (generic types) but I don't know how it will perform under heavy usage that's why I wanted to do the many to many fields.
If you are interested in the total number of usage ( aka reference count ) of a tag very often, I think you should store it in the database, example put one extra field to the Tag model, like
referencecount = models.IntegerField( default=0 )
Than in the appropriate places, ( example models .save() )you can increment or decrements it's value.
For your use case, the performance of generic wouldn't matter, because you need anyway to do N queries over 2N tables (one for each "taggable" model and one for each m2m join table, at least).
With the m2m approach, you should have the list of 'taggable' models stored somewhere, at least as a list of ('app_name', 'model') pairs. Then use ContentType (it's very performant) to get the actual model class or query directly from there:
counts = {}
for m in taggable_models:
ct = ContentType.get_by_natural_key(*m)
c = ct.model_class().objects.filter(tags=yourtag).distinct().count()
counts[ct.name] = c