预取相关django

alg*_*los 4 python django django-queryset

我正在开发用Django编写的应用程序,但在使用select_related和prefetch_related进行正确请求时遇到一些问题

我有三种型号:

class Intervention(BaseModel):
    date = DateField()
    housing = ForeignKey('contract.Housing', related_name='interventions')

class Housing(BaseModel):
    address = CharField(max_length=CHAR_FIELD_LENGTH) 

class Tenant(BaseModel):
    name = CharField(max_length=CHAR_FIELD_LENGTH)
    phone = CharField(max_length=CHAR_FIELD_LENGTH, blank=True, null=True)
    housing = ForeignKey(Housing, related_name='tenants')
Run Code Online (Sandbox Code Playgroud)

我要求干预模型,如果要访问房屋信息,只需使用select_related:

Interventions.object.select_related("housing").filter(...)
Run Code Online (Sandbox Code Playgroud)

但是我不知道如何使用prefetch_related访问租户:

Interventions.object.select_related("housing").prefetch_related("housing__tenants") 
Run Code Online (Sandbox Code Playgroud)

似乎不起作用,因为每次我尝试访问租户列表时都会进行查询。有没有一种方法可以访问租户列表,最好是对I进行过滤(例如找到第一个没有名称的租户)。

感谢您的回答。

阿尔盖洛斯

* 编辑:这是一些代码:*

我要求像我说的那样:

interventionPreventivesVisits = InterventionPreventiveVisit.objects.select_related("housing").prefetch_related("housing__tenants").filter(date__range=(self.weekDays[0], self.weekDays[len(self.weekDays)-1]))
Run Code Online (Sandbox Code Playgroud)

self.weekDays是一个天数表,用于在日历中显示干预。

然后,我要显示没有名称的承租人:

在我的模板中,我遍历干预:

{%for inter in interventions %}
    {%if day == inter.date %}
        {{ inter | get_schedule_html_formated | safe}}
    {%endif%}
{% endfor %}
Run Code Online (Sandbox Code Playgroud)

我有一个templateTag来显示HTML:

def get_schedule_html_formated(intervention):
    housingTenant = None
    for tenant in intervention.housing.tenants.all(): # Here it does a query
        if tenant.name is not None:
            housingTenant = tenant
    ....
Run Code Online (Sandbox Code Playgroud)

然后我写并返回我的html

我正在寻找一种无需做新查询即可设置HousingTenant的方法。

那个更好吗 :) ?

ndp*_*dpu 5

从这里https://docs.djangoproject.com/en/dev/ref/models/querysets/#prefetch-related

select_related通过创建SQL连接并将相关对象的字段包括在SELECT语句中来工作。因此,select_related在同一数据库查询中获取相关对象。但是,为了避免跨“许多”关系进行联接会产生更大的结果集,select_related仅限于单值关系-外键和一对一关系。

另一方面,prefetch_related 对每个关系进行单独的查找,并在Python中进行“加入”

更新评论:

最好先在此处放置过滤器(django中的顺序可能会影响结果):

interventionPreventivesVisits = InterventionPreventiveVisit.objects.filter(
    date__range=(self.weekDays[0], self.weekDays[len(self.weekDays)-1])
).select_related("housing"
).prefetch_related("housing__tenants")
Run Code Online (Sandbox Code Playgroud)