Django:通过查询计算列值之和

148

我有一个模型:

class ItemPrice(models.Model):
     price = models.DecimalField(max_digits=8, decimal_places=2)
     # ...

我尝试使用以下代码计算这个查询集中 price 的总和:

items = ItemPrice.objects.all().annotate(Sum('price'))

这个查询有什么问题吗?还有其他什么方法可以计算price列的总和吗?

我知道可以在查询集上使用for循环来完成,但我需要一种优雅的解决方案。

谢谢!


这个回答解决了你的问题吗?Django SUM 查询? - Flimm
7个回答

309

你可能正在寻找aggregate函数。

from django.db.models import Sum

ItemPrice.objects.aggregate(Sum('price'))
# returns {'price__sum': 1000} for example

1
我该如何获取价格为5000的总数量? - Anuj Sharma
14
记住,返回的是字典而不是浮点数或整数,例如 {'price__sum':1000}。可以使用yourdict['price__sum']来获得浮点数或整数。 - Josh

64

请参考我下面的示例,使用 .aggregate(Sum('column'))['column__sum']

sum = Sale.objects.filter(type='Flour').aggregate(Sum('column'))['column__sum']

1
我遇到了一个错误: 'decimal.Decimal' 对象不可迭代。 - Roni X

53

Annotate会在结果中添加一个字段:

>> Order.objects.annotate(total_price=Sum('price'))
<QuerySet [<Order: L-555>, <Order: L-222>]>

>> orders.first().total_price
Decimal('340.00')

Aggregate 返回一个包含所请求结果的字典:

>> Order.objects.aggregate(total_price=Sum('price'))
{'total_price': Decimal('1260.00')}

我感谢您展示如何指定key来将总和value存储到其中。 - MikeyE

11

使用 cProfile 分析器,我发现在我的开发环境中,对列表进行求和比使用 Sum() 聚合更有效率(更快)。

sum_a = sum([item.column for item in queryset]) # Definitely takes more memory.
sum_b = queryset.aggregate(Sum('column')).get('column__sum') # Takes about 20% more time.

我在不同的情境下进行了测试,似乎使用 aggregate 总是需要更长的时间来产生相同的结果。虽然我怀疑使用它可能在内存方面有优势,而不是对列表求和。


6
或者,使用生成器表达式代替列表:sum_a = sum(item.column for item in queryset)。唯一的区别是删除了[]。这样可以节省内存空间,在sum()迭代整个列表之前计算整个列表。 - Code-Apprentice
出现错误:'decimal.Decimal' 对象不可迭代。 - Roni X

7

之前的回答已经很好了,此外,您可以使用一行普通代码获得总数...

items = ItemPrice.objects.all()
total_price = sum(items.values_list('price', flat=True))

4

你也可以用以下方式得到总和:

def total_sale(self):
    total = Sale.objects.aggregate(TOTAL = Sum('amount'))['TOTAL']
    return total

将“amount”替换为您要计算总和的模型中的列名,将“Sale”替换为您的模型名称。


请不要忘记导入Sum:from django.db.models import Sum - Frank Fayia Kendemah

2

您需要使用 aggregate()Sum() 来计算如下所示的 price 列的总和。*带有 all() 的查询与不带 all() 的查询等效,如下所示:

from django.db.models import Sum

print(ItemPrice.objects.all().aggregate(Sum('price')))
print(ItemPrice.objects.aggregate(Sum('price')))

然后,以下这些字典将被输出到控制台:

{'price__sum': Decimal('150.00')}
{'price__sum': Decimal('150.00')}

而且,您可以将默认键price__sum更改为priceSum,以用于价格列,如下所示:

from django.db.models import Sum
                                        # ↓ Here
print(ItemPrice.objects.all().aggregate(priceSum=Sum('price')))
print(ItemPrice.objects.aggregate(priceSum=Sum('price')))
                                  # ↑ Here

然后,将默认密钥更改如下:

{'priceSum': Decimal('150.00')}
{'priceSum': Decimal('150.00')}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接