【问题标题】:Prefetch object not working with order_by queryset预取对象不适用于 order_by 查询集
【发布时间】:2018-09-30 10:37:43
【问题描述】:

将 Django 11 与 PostgreSQL 数据库一起使用。我有如下所示的模型。我正在尝试使用 Prefetch 对象和 prefetch_related 而不将其分配给属性来预取相关的查询集。

class Person(Model):
    name = Charfield()

    @property
    def latest_photo(self):
        return self.photos.order_by('created_at')[-1]

class Photo(Model):
    person = ForeignKey(Person, related_name='photos')
    created_at = models.DateTimeField(auto_now_add=True)


first_person = Person.objects.prefetch_related(Prefetch('photos', queryset=Photo.objects.order_by('created_at'))).first()

first_person.photos.order_by('created_at') # still hits the database
first_person.latest_photo # still hits the database

在理想情况下,调用person.latest_photo 不会再次访问数据库。这将允许我在列表显示中安全地使用该属性。 但是,正如代码中的 cmets 所述,当我尝试获取最新照片时,未使用预取的查询集。这是为什么呢?

注意:我尝试使用 Prefetchto_attr 参数,这似乎有效,但是,这并不理想,因为这意味着我必须编辑 latest_photo 才能尝试使用预取属性。

【问题讨论】:

  • latest_photo 方法中调用order_by('created_at') 会创建一个新的查询集,因此不会使用预取的对象。另一种获取最新照片的方法是使用subquery
  • 有没有办法用 order_by 预取?另外,您能否详细说明使用子查询预取的情况?
  • 我已经为您链接到子查询文档,我无法将查询写在脑海中。是的,您可以在prefetch 中使用order_by。问题是您在 latest_photo 方法中使用了不同/额外的 order_by
  • 如果我想让你使用最初预取的 order_by 的结果,我该怎么做?

标签: python django query-optimization


【解决方案1】:

问题在于切片,它会创建不同的查询。

你可以这样解决它:

    ...

    @property
    def latest_photo(self):
        first_use_the_prefetch = list(self.photos.order_by('created_at'))
        then_slice = first_use_the_prefetch[-1]
        return then_slice

如果您想尝试,则无法在 Prefetch(query=...no slicing here...) 中使用切片(在 Django 跟踪器中的某处有一个 wontfix 功能请求)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-09
    • 2019-03-20
    • 1970-01-01
    • 1970-01-01
    • 2015-11-15
    • 1970-01-01
    相关资源
    最近更新 更多