我正在开发一个用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而不进行新的查询。
那更好:)?
答案 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]))