Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django chaining prefetch_related and select_related

Let's say I have following models

class Foo(models.Model):
    ...

class Prop(models.Model):
    ...

class Bar(models.Model):
    foo: models.ForeignKey(Foo, related_name='bars', ...)
    prop: models.ForeignKey(Prop, ...)

Now I want to make the following query.

foos = Foo.objects.prefetch_related('bars__prop').all()

Does the above query makes 3 Database calls or only 2 (select_related for prop from bar), given that only one prop is associated with bar

If it takes 3 calls then, is there a way to make it 2 calls by using selected_related for bar -> prop

like image 651
Pavan Kumar Avatar asked Feb 07 '19 08:02

Pavan Kumar


People also ask

What is the difference between Select_related and Prefetch_related in Django?

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.

What is the use of Select_related () in Django ORM query?

Django offers a QuerySet method called select_related() that allows you to retrieve related objects for one-to-many relationships. This translates to a single, more complex QuerySet, but you avoid additional queries when accessing the related objects. The select_related method is for ForeignKey and OneToOne fields.

How does prefetch related work?

prefetch_related does a separate lookup for each relationship, and performs the “joining” in Python. It is different from select_related , the prefetch_related made the JOIN using Python rather than in the database. Let's dig into it with an example. We have 10 stores in the database and each store has 10 books.

What is QuerySet in Django?

A QuerySet is a collection of data from a database. A QuerySet is built up as a list of objects. QuerySets makes it easier to get the data you actually need, by allowing you to filter and order the data.


1 Answers

You can use the Prefetch class to specify the queryset that is used in prefetch_related() and this way combine it with select_related():

from django.db.models import Prefetch
bars = Bar.objects.select_related('prop')
foos = Foo.objects.prefetch_related(Prefetch('bars', queryset=bars)).all()

Note that this should be two queries, one for the Foo objects and one for getting the related Bar objects that are being joined in the same query with Prop.

like image 107
Bernhard Vallant Avatar answered Sep 21 '22 12:09

Bernhard Vallant