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?
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