Prefetch_related django

时间:2013-12-03 09:22:07

标签: 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')

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

Interventions.object.select_related("housing").filter(...)

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

Interventions.object.select_related("housing").prefetch_related("housing__tenants") 

似乎不起作用,因为它每次我尝试访问租户列表时都会进行查询。 有没有办法访问租户列表,最好是对我进行过滤(就像找到没有名字的第一个租户一样)。

谢谢你的答案。

Algelos

* 编辑:以下是一些代码:*

我正在请求,就像我说的那样:

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

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

然后,我想显示没有名字的租户:

在我的模板中,我循环介绍了干预措施:

{%for inter in interventions %}
    {%if day == inter.date %}
        {{ inter | get_schedule_html_formated | safe}}
    {%endif%}
{% endfor %}

我有一个模板标签来显示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
    ....

然后我写并返回我的HTML

我正在寻找一种方法来设置housingTenant而不进行新的查询。

那更好:)?

2 个答案:

答案 0 :(得分:5)

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

  

select_related通过创建SQL连接并包含字段来工作   SELECT语句中的相关对象。为此原因,   select_related获取同一数据库查询中的相关对象。   但是,要避免由此产生的更大的结果集   加入'many'关系时,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")

答案 1 :(得分:1)

尝试使用:

interventionPreventivesVisits = InterventionPreventiveVisit.objects.prefetct_related("housing__tenants").filter(date__range=(self.weekDays[0], self.weekDays[len(self.weekDays)-1]))