【问题标题】:Prefetch related django预取相关django
【发布时间】:2013-12-03 09:22:06
【问题描述】:

我正在开发一个用 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") 

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

感谢您的回答。

阿尔杰洛斯

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

我要求就像我说的那样:

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 的方法。

这样更好吗:)?

【问题讨论】:

    标签: python django django-queryset


    【解决方案1】:

    从这里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")
    

    【讨论】:

    • 嗨,我尝试在租户上不使用“s”,但它会导致错误:'housing__tenant' is an invalid parameter to prefetch_related(),这似乎是逻辑,因为我的相关名称是租户。关于 PREfetch,这只是写我的问题时的一个错误,我将对其进行编辑:)。所以,你最后用粗体引用的话,你是说如果不再做一个请求,我就无法访问我的租户。我的解释正确吗?
    • @alglos 你对租户的看法是对的,但现在它应该可以工作了。我认为是正确的,一个额外的预取查询,你可以在没有额外查询的情况下访问租户
    • @npdu,好的,谢谢你的回答。因此,如果我循环干预以获取租户,我的查询将自动取决于我的干预次数:/我有什么办法避免这种情况吗? (就像我说的,我只想要找到的第一个没有名字的租户,所以也许有 custom_values,或者什么?我真的是这种请求的新手^^)
    • 我将它添加到我的编辑下
    • @algelos 更改订单没有帮助? (我不使用 all() 的建议是错误的)
    【解决方案2】:

    试试这个:

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

    【讨论】:

      猜你喜欢
      • 2018-11-11
      • 2020-05-09
      • 2012-09-10
      • 1970-01-01
      • 2021-11-28
      • 1970-01-01
      • 1970-01-01
      • 2021-08-15
      • 2015-05-02
      相关资源
      最近更新 更多