有没有一种方法可以使用额外的属性来扩展django QuerySet?
问题内容:
我正在尝试向QuerySet的元素添加一些额外的属性,以便可以在模板中使用额外的信息,而不是多次访问数据库。让我以示例为例进行说明,假设我们有一本带有作者外键的书。
>>> books = Book.objects.filter(author__id=1)
>>> for book in books:
... book.price = 2 # "price" is not defined in the Book model
>>> # Check I can get back the extra information (this works in templates too):
>>> books[0].price
2
>>> # but it's fragile: if I do the following:
>>> reversed = books.reverse()
>>> reversed[0].price
Traceback (most recent call last):
...
AttributeError: 'Book' object has no attribute 'price'
>>> # i.e., the extra field isn't preserved when the QuerySet is reversed.
因此,只要不使用诸如reverse()之类的东西,就可以向QuerySet的元素添加属性。
我当前的解决方法是仅使用select_related()从数据库再次获取所需的额外信息,即使我已经在内存中了。
有更好的方法吗?
问题答案:
出现错误是因为qs.reverse()产生了一个新的QuerySet实例,因此您没有反转旧的实例。
如果要采取行动的基本QS,可以执行以下操作:
>>> augmented_books = Book.objects.extra(select={'price': 2))
>>> augmented_books[0].price
2
>>> augmented_books_rev = augmented_books.reverse()
>>> augmented_books_rev[0].price
2
当然,select
关键字可能要复杂得多,实际上,它几乎可以是任何适用于[XXX]
in的有意义的SQL代码段
SELECT ..., [XXX] as price, ... FROM ... WHERE ... (etc)
编辑
正如其他回应所指出的那样,该解决方案 可能 效率不高。
如果确定要从查询中获取 所有 Book对象,则最好进行一个查询,将其存储在列表中,并最终反转结果列表。
另一方面,如果要获取表的“ head”和“ queue”,则进行两次查询会更好,因为您不会查询所有“中间”无用的对象。