If my Models look like:
class Publisher(models.Model): pass class Book(models.Model): publisher = models.ForeignKey(Publisher) class Page(models.Model): book = models.ForeignKey(Book)
and I would like to get the queryset for Publisher
I do Publisher.object.all()
. If then want to make sure to prefetch I can do:
Publisher.objects.all().prefetch_related('book_set')`
My questions are:
select_related
or must I use prefetch_related
?page_set
? This does not work:Publisher.objects.all().prefetch_related('book_set', 'book_set_page_set')
select_related() "follows" foreign-key relationships, selecting additional related-object data when it executes its query. prefetch_related() does a separate lookup for each relationship, and does the "joining" in Python.
In Django, select_related and prefetch_related are designed to stop the deluge of database queries that are caused by accessing related objects. In this article, we will see how it reduces the number of queries and make the program much faster.
Since Django 1.7, instances of django.db.models.Prefetch
class can be used as an argument of .prefetch_related
. Prefetch
object constructor has a queryset
argument that allows to specify nested multiple levels prefetches like that:
Project.objects.filter( is_main_section=True ).select_related( 'project_group' ).prefetch_related( Prefetch( 'project_group__project_set', queryset=Project.objects.prefetch_related( Prefetch( 'projectmember_set', to_attr='projectmember_list' ) ), to_attr='project_list' ) )
It is stored into attributes with _list
suffix because I use ListQuerySet
to process prefetch results (filter / order).
No, you cannot use select_related
for a reverse relation. select_related
does a SQL join, so a single record in the main queryset needs to reference exactly one in the related table (ForeignKey
or OneToOne
fields). prefetch_related
actually does a totally separate second query, caches the results, then "joins" it into the queryset in python. So it is needed for ManyToMany
or reverse ForeignKey
fields.
Have you tried two underscores to do the multi level prefetches? Like this: Publisher.objects.all().prefetch_related('book_set', 'book_set__page_set')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With