Django:prefetch_related() 是不是遵循反向关系查找?

Posted

技术标签:

【中文标题】Django:prefetch_related() 是不是遵循反向关系查找?【英文标题】:Django: Does prefetch_related() follow reverse relationship lookup?Django:prefetch_related() 是否遵循反向关系查找? 【发布时间】:2012-02-28 21:23:21 【问题描述】:

我在 django 1.4 中从trunk 尝试了 prefetch_related(),但无法预取反向查找。

我的简化模型(每本书都有很多价格):

class Book(models.Model):
    # some fields

class Price(models.Model):
    book = models.ForeignKey(Book)

我的观点的查询:

books = Book.objects.prefetch_related('price')

然后,我收到了 AttributeError 消息:

AttributeError: Cannot find 'price' on Book object, 'price' is an invalid parameter to prefetch_related()

如何让它发挥作用? 谢谢。

【问题讨论】:

【参考方案1】:

定义相关名称:

class Price(models.Model):
    book = models.ForeignKey(Book, related_name='prices')

然后使用它:

books = Book.objects.prefetch_related('prices')

【讨论】:

你的回答让我想起了 FOO_set,所以更正也可以是 .prefetch_related('price_set')。顺便说一句,非常感谢 我无法在 shell 中重现它。仍然做单独的查询,我期待加入。 您好!我也试过这个,但正如@pdvyas 所说,有单独的查询。这不会进行连接... prefetch_related 不进行连接,它只是收集相关对象 ID,然后在单个查询中获取这些对象并在 Python 中生成这些“连接”。见:docs.djangoproject.com/en/dev/ref/models/querysets/… @jan-pöschko,似乎是定义related_name 的(更简单的)替代方法,是使用price_set 名称来引用关系。我已经添加了一个描述这一点的答案,但也许最好在你的(接受的)分析器中参考我的答案,或者在你的分析器中包含我的文本?【参考方案2】:

当您没有为关系定义related_name 时,反向关系会附加_set。从对象(例如some_book.price_set.all())访问反向关系时就是这种情况,但这也适用于prefetch_related

books = Book.objects.prefetch_related('price_set')

请注意,这似乎与过滤器不同,过滤器确实接受没有_set 的其他模型的名称(例如Books.objects.filter(price__currency='EUR'))。

上面是用 1.11.8 测试的(不是在这个特定的代码上,而是在我自己的类似代码上)。

或者,您可以添加related_name,如上面的 Jan Pöschko 所示。

【讨论】:

以上是关于Django:prefetch_related() 是不是遵循反向关系查找?的主要内容,如果未能解决你的问题,请参考以下文章

Django:prefetch_related 没有效果

prefetch_related 上的 Django ORM 注释

django prefetch_related 很多查询

Django - 过滤 prefetch_related 查询集

Django prefetch_related 与限制

为啥 django 的 prefetch_related() 只适用于 all() 而不是 filter()?