如何在Django中为相关字段预取_related字段

o2g1uqev  于 2023-03-24  发布在  Go
关注(0)|答案(1)|浏览(132)

我看过一些关于如何在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')
    )
)

如何预取所有相关内容?

b09cbbtk

b09cbbtk1#

应该可以使用:

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

相关问题