通过动态添加的字段重新排序Django QuerySet

时间:2017-09-14 11:19:24

标签: python django django-queryset

有一段代码,它从DB中获取一些QuerySet,然后将新的计算字段附加到查询集中的每个对象。通过注释添加此字段不是一个选项(因为它是遗留的,因为这个计算基于另一个已经预先获取的数据)。

像这样:

from django.db import models
class Human(models.Model):
    name = models.CharField()
    surname = models.CharField()

def calculate_new_field(s):
   return len(s.name)*42

people = Human.objects.filter(id__in=[1,2,3,4,5])

for s in people:
   s.new_column = calculate_new_field(s)
# people.somehow_reorder(new_order_by=new_column)

所以现在QuerySet中的所有人都有一个新列。我希望通过new_column字段对这些对象进行排序。 order_by()显然不起作用,因为它是一个数据库选项。我知道我可以将它们作为一个排序列表传递,但是有很多模板和其他逻辑,它们希望从这个对象开始使用类似QuerySet的方法等等。

所以问题是:是否有一些非常糟糕和肮脏的方法通过dinamically添加字段重新排序现有QuerySet或使用此数据创建新的类QuerySet对象?我相信我不是唯一一个遇到这个问题的人,而且已经用django解决了。但我找不到任何东西(除了添加第三方库,这也不是一个选项)。

2 个答案:

答案 0 :(得分:0)

你能试试functions.Length

from django.db.models.functions import Length

qs = Human.objects.filter(id__in=[1,2,3,4,5])
qs.annotate(reorder=Length('name') * 42).order_by('reorder')

答案 1 :(得分:0)

从概念上讲,QuerySet不是结果列表,而是"指令来获取这些结果"。它被懒惰地评估并缓存。保存缓存结果的QuerySet的内部属性为Command+Option+Shift+K

因此,qs._result_cache句子强制评估查询并缓存结果。

之后,您可以通过执行以下操作对结果进行排序:

for s in people

但是,在评估QuerySet之后,(在我看来)保留QuerySet接口没有多大意义,因为许多操作都会导致重新评估查询。从这一点开始,您应该处理模型列表