How to combine django "prefetch_related" and "values" methods? - python

How can prefetch_related and values method be applied in combination?
Previously, I had the following code. Limiting fields in this query is required for performance optimization.
Organizations.objects.values('id','name').order_by('name')
Now, I need to prefetch its association and append it in the serializer using "prefetch_related" method.
Organizations.objects.prefetch_related('locations').order_by('name')
Here, I cannot seem to find a way to limit the fields after using "prefetch_related".
I have tried the following, but on doing so serializer does not see the associated "locations".
Organizations.objects.prefetch_related('locations').values("id", "name").order_by('name')
Model Skeleton:
class Organizations(models.Model):
name = models.CharField(max_length=40)
class Location(models.Model):
name = models.CharField(max_length=50)
organization = models.ForeignKey(Organizations, to_field="name", db_column="organization_name", related_name='locations')
class Meta:
db_table = u'locations'

Use only() to limit number of fields retrieved if you're concerned about your app performances. See reference.
In the example above, this would be:
Organizations.objects.prefetch_related('locations').only('id', 'name').order_by('name')
which would result in two queries:
SELECT id, name FROM organizations;
SELECT * from locations WHERE organization_name = <whatever is seen before>;

Related

Ordering Model based on a max Children Attribute (with potential ties) - Django

I would like to sort my Docket object based on the most recent Document (a child object). There are typically several documents with the same date_filed. Based on the tutorial, I tried sorting on -documents__date_filed and it sort of works. Because there are multiple Documents with the exact same date, my ListView shows 2-3 repeated rows (one for each date tie). How do I avoid getting the duplicated results and just have one row for each Docket in the output?
class Docket(models.Model):
name = models.CharField(max_length=200)
class Meta:
ordering = ['-documents__date_filed', Func(F('name'), function='LOWER')]
class Document(models.Model):
docket = models.ForeignKey(Docket, on_delete=models.CASCADE, related_name="documents")
date_filed = models.DateTimeField(default=timezone.now)
It might be better to do the ordering in the ListView itself if it includes a related model, since now nearly all Docker.objects.all() querysets will have duplicates.
You can make use of .distinct() [Django-doc] to retrieve a queryset of Docket objects where the same one only occurs once:
from django.views.generic import ListView
from django.db.models.functions import Lower
class DocketListView(ListView):
model = Docket
queryset = Docket.objects.order_by(
'-documents__date_filed',
Lower('name')
).distinct()

How do I write a Django ORM query where the select table shares a common column with another table?

I'm using Django and Python 3.7. I have these two models. Note they both have a similar field
class Article(models.Model):
publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE,)
class WebPageStat(models.Model):
objects = WebPageStatManager()
publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE, )
score = models.BigIntegerField(default=0)
I would like to write a Django ORM query that selects one of the models but does a join on the shared column in order to do a comparison on the "score" field. I tried the below, but alas the error
Article.objects.filter(publisher=webpagestat.publisher, webpagestat.score__gte==100)
File "<input>", line 1
SyntaxError: positional argument follows keyword argument
How do I include the "WebPageStat" table in my join?
What you want is easily done in Django by using lookups that span relations. In your example you need to add a way of referencing the related objects in the ORM. This is donde by setting the related_name attribute of the ForeignKey fields. Although this is not strictly necessary it is more clear in this way. You can read more about related_name and related_query_name here. In short, your models should look like:
class Article(models.Model):
publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE, related_name='articles')
class WebPageStat(models.Model):
objects = WebPageStatManager()
publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE, related_name='stats')
score = models.BigIntegerField(default=0)
Once this is done your query will be carried out by the following code:
Article.objects.filter(publisher__stats__score__gte=100)
What this query is doing in short is selecting every article whose publisher has at least one web page stat whose score is greater than or equal to 100.

Django Filter on most common occurrence in many to many field

I would like to filter/exclude my query-set based on the most common occurrence (mode) of my many to many field which is a charfield:
For example in my example below I would like to filter among the classes that contain classrooms with students where "David" is the most common name in the class. (Django version 1.9.2)
#models.py
class Student(models.Model):
name = models.CharField()
class Class(models.Model):
name = models.CharField()
students = models.ManyToManyField(Student)
#views.py
Class.objects.filter(students__mode = 'David')
you need django aggregations doc
your query will be something like this (I'm not sure it's the exact query or not but using the docs and this sample you will get the idea how it works)
Class.objects.filter(
students__name="David"
).annotate(
david_count=Count('students')
).order_by(
'david_count'
)

Django: Referencing a manytomany field that has been defined in another model

I'm trying to work out how to calculate the number of books written by an author. The book model sets up the manytomany field with the author model. I have no idea how even google something like this which I thought would be very simple to do but I don't even know how to start.
Here's the stripped down code:
class Author(models.Model):
first_name = models.CharField()
last_name = models.CharField()
def books(self):
"""Return a list of comma separated list of books by the author"""
pass
class Book(models.Model):
title = models.CharField()
authors = models.ManyToManyField(Author)
Maybe I could do a filter query to get books by a particular author but it doesn't seem like the django way to do it? I'm also not sure how to pass the filter function a python object rather than text.
Thanks
when you define a foreignkey or manytomany field, django sets up a reverse relation for you, which in your case is book_set. so something like:
def books(self):
books = self.book_set.all()
return ', '.join([book.title for book in books])
see related objects in the docs

queries in django

How to query Employee to get all the address related to the employee, Employee.Add.all() does not work..
class Employee():
Add = models.ManyToManyField(Address)
parent = models.ManyToManyField(Parent, blank=True, null=True)
class Address(models.Model):
address_emp = models.CharField(max_length=512)
description = models.TextField()
def __unicode__(self):
return self.name()
Employee.objects.get(pk=1).Add.all()
You need to show which employee do you mean. pk=1 is obviously an example (employee with primary key equal to 1).
BTW, there is a strong convention to use lowercase letters for field names. Employee.objects.get(pk=1).addresses.all() would look much better.
Employee.Add.all() does not work because you are trying to access a related field from the Model and this kind of queries require an instance of the model, like Ludwik's example. To access a model and its related foreign key field in the same query you have to do something like this:
Employee.objects.select_related('Add').all()
That would do the trick.
employee = Employee.objects.prefetch_related('Add')
[emp.Add.all() for emp in employee]
prefetch_related supports many relationships and caches the query set and reduces the database hits hence increases the performance..

Categories

Resources