如何在Django中对一个相关字段进行预取(prefetch_related)操作?

5

我看过一些关于在Django中如何预获取正向和反向关系中的prefetch_related字段的示例,但我对于如何应用它来预获取所有相关模型的字段存有疑虑。

例如,如果我想要从以下模型获取所有内容,以HealthCheck作为起点。最优化的查询方式是什么?

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)

我尝试过类似的东西,但似乎不起作用:
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')
    )
)

我该如何预取所有相关的内容?

1个回答

5

这应该是可能的:

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

select_related 会获取所有相关字段,直到 profile

prefetch_related 应该预取所有相关对象,直到 vaccines

编辑:测试并确认当我为一个健康检查人创建了3个疫苗对象时,只生成了2个查询(n是我的函数来计算执行的查询):

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

 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接