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

Tia*_*imo 48 django django-models django-queryset

我已经在trunk中尝试了django 1.4中的prefetch_related(),并且无法使其预取反向查找.

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

class Book(models.Model):
    # some fields

class Price(models.Model):
    book = models.ForeignKey(Book)
Run Code Online (Sandbox Code Playgroud)

我的观点是:

books = Book.objects.prefetch_related('price')
Run Code Online (Sandbox Code Playgroud)

然后,我收到了AttributeError消息:

AttributeError: Cannot find 'price' on Book object, 'price' is an invalid parameter to prefetch_related()
Run Code Online (Sandbox Code Playgroud)

如何使它工作?谢谢.

Jan*_*hko 86

定义相关名称:

class Price(models.Model):
    book = models.ForeignKey(Book, related_name='prices')
Run Code Online (Sandbox Code Playgroud)

然后使用它:

books = Book.objects.prefetch_related('prices')
Run Code Online (Sandbox Code Playgroud)

  • 你的回答让我想起了FOO_set,所以修正也可以是.prefetch_related('price_set').顺便说一句,非常感谢 (36认同)
  • `prefetch_related`不进行连接,只收集相关的对象ID,然后在单个查询中获取这些对象,并在Python中生成这些'连接'.请参阅:https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.prefetch_related (7认同)

Mat*_*man 17

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

books = Book.objects.prefetch_related('price_set')
Run Code Online (Sandbox Code Playgroud)

需要注意的是,这似乎不同于过滤器,它接受其他型号没有的名称_set(如Books.objects.filter(price__currency='EUR')).

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

或者,您可以添加一个related_name,如上面的JanPöschko所示.