8

I have seem some examples of how to prefetch_related fields in a forward and backward relationship in Django, but I have doubts about how can this be applied if we want to prefetch all the fields of a related model.

For instance if I want to fetch all content from the following models, using HealthCheck as the starting point. Which would be the most optimized query to achieve that?

class HealthCheck(models.Model):
    id = models.Integer()
    person = models.ForeignKey('Person')


class Person(models.Model):
    profile = models.ForeignKey('Profile')
    vaccines = models.ManyToManyField('vaccines', through='PersonVaccines')


class Profile(models.Model):
    name = models.CharField(max_length=16)


class PersonVaccines(models.Model):
    person = models.ForeignKey(Person)
    vaccine = models.ForeignKey('Vaccine')


class Vaccine(models.Model):
    name = models.CharField(max_length=16)

I have tried something like this but doesn't seems to work:

from django.db.models import Prefetch

HealthCheck.objects.filter(id=1).prefetch_related(
    Prefetch(
        'person__vaccines',
        queryset=PersonVaccines.objects.select_related('person', 'person__profile', 'vaccine')
    )
)

How can I prefetch all the related content?

1 Answer 1

6

It should be possible with:

HealthCheck.objects.filter(
    id=1,
).select_related(
    'person__profile',
).prefetch_related(
    'person__vaccines',
)

select_related will fetch all the related fields until profile.

prefetch_related should then prefetch all the related objects until vaccines

EDIT: Tested and confirmed that only 2 queries are generated when I created 3 vaccine objects for one health check person (n is my function to count queries executed):

In [2]: health_check = HealthCheck.objects.filter(id=3).select_related('person__profile').prefetch_related('person__vaccines').get()
     ...:

In [3]: n()
2

In [4]: for v in health_check.person.vaccines.all():
     ...:     print(v.name)
     ...:
v1
v2
v3

In [5]: n()
0

 
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.