我发现了一些类似于我的问题,但是大多数问题已经过时,或者过于(或太少)冗长而且有用。
我有一个这样的模型:
class Breakfast(models.Model):
count_eggs = models.IntegerField()
count_bacon = models.IntegerField()
had_toast = models.BooleanField()
现在,在构建RESTful API时,我需要能够按count_eggs + count_bacon
总计对Breakfast对象进行排序,而不会将其永久存储在模型上。
许多当前和流行的问题都表明这样的事情:
Breakfast.objects.extra(
select={'total_food':'count_eggs + count_bacon'},
order_by=('total_food',)
)
这似乎适用于许多人,但Django docs appear to dissuade this solution。那么,在1.10+世界中,对Django中两个(或更多)字段的总和进行此类过滤的最佳/正确方法是什么
答案 0 :(得分:4)
你应该使用注释,我有一个我的例子并适应你的情况,试试这个:
from django.db.models import F, Sum
Breakfast.objects.all().\
annotate(total_food=Sum(
F('count_eggs ') + F('count_bacon'))
).\
order_by('total_food')
答案 1 :(得分:2)
Latrovas的答案略有改动,虽然他的查询可行,但SUM和GROUP_BY是不必要的。
更直观的查询如下:
Breakfast.objects.all().\
annotate(total_food=F('count_eggs ') + F('count_bacon')
).order_by('total_food')
我想更进一步,向您解释查询在幕后的工作原理:
当我们注释时,我们实际上是在SQL的SELECT
语句中添加一列。因此,为了执行两个字段的添加,我们需要一个像SELECT (eggs + bacon) as food
这样的选择语句。
这完全 annotate
在幕后所做的事情。
但是,我们需要使用存储在数据库中的项目,而不是使用硬编码值,即eggs
和bacon
表达式等列名。
这完全 F()
表达式的作用。
现在这是一个时间问题,你才意识到,因为他们做了两件完全不同的事情,我们可以轻松地将两者结合起来,并将它们一起用于一些非常强大的东西!