Django聚合:仅求和返回值?

Posted

技术标签:

【中文标题】Django聚合:仅求和返回值?【英文标题】:Django Aggregation: Sum return value only? 【发布时间】:2013-10-08 22:28:34 【问题描述】:

我有一个已支付价值的列表,并希望显示已支付的总金额。我使用聚合和Sum 一起计算值。问题是,我只想打印出总值,但会打印出聚合:'amount__sum': 480.0(480.0 是总增值。

在我看来,我有:

    from django.db.models import Sum

    total_paid = Payment.objects.all.aggregate(Sum('amount'))

为了在页面上显示值,我有一个带有以下内容的 mako 模板:

    <p><strong>Total Paid:</strong> $total_paid</p>

如何让它显示480.0 而不是'amount__sum': 480.0

【问题讨论】:

aggregate(sum = Sum('amount')) 和模板中的$total_paid.sum 怎么样 【参考方案1】:

我不相信有办法只获得价值。

您可以在模板中使用$ total_paid.amount__sum 。或者在你的视野里做total_paid = Payment.objects.all().aggregate(Sum('amount')).get('amount__sum', 0.00)

编辑

正如其他人指出的那样,.aggregate() 将始终返回一个包含来自聚合的所有键的字典,因此不需要对结果执行.get()。但是,如果查询集为空,则每个聚合值将为 None。因此,根据您的代码,如果您期望浮动,您可以这样做:

total_paid = Payment.objects.all().aggregate(Sum('amount'))['amount__sum'] or 0.00

【讨论】:

谢谢你。我已经尝试过 $ total_paid.amount__sum 但它没有用。但是在视图中调用它效果很好! @jproffitt,如果聚合成功执行,您将没有带有键 'amount__sum' 的字典,您能给我举个例子吗? @lmiuelvargasf 你是对的。没有必要做.get。我已对我的答案进行了编辑。【参考方案2】:

给它一个名字,然后问它:

total_paid = Payment.objects.all.aggregate(sum=Sum('amount'))['sum']

应该更具可读性,并且不需要转换。

【讨论】:

这是最短最简洁的答案 请注意,尽量不要使用内置函数的名称,例如sum【参考方案3】:

aggregate() 方法返回一个字典。如果你知道你只返回一个单项字典,你可以使用.values()[0]

Python 2 中:

total_paid = Payment.objects.aggregate(Sum('amount')).values()[0]

Python 3 中,(感谢 @lmiuelvargasf)这需要:

total_paid = list(Payment.objects.aggregate(Sum('amount')).values())[0]

最终结果与@jproffitt 的答案相同,但它避免了重复amount__sum 部分,因此更通用一些。

【讨论】:

这也是我的首选解决方案。 values() 在 Python 3 中有 changed 以返回视图而不是列表。将values() 的返回值传递给list() 可以使这个解决方案发挥作用。 我同意@TaylorEdmiston,此代码不适用于 Python 3。我添加了一个解决它的答案。 谢谢@lmiuelvargasf。为了将来帮助其他人,我还刚刚提交了对此答案的社区编辑,添加了 python 3 行。我相信在同行批准后其他人可以看到它。【参考方案4】:

在 Python 3 中

您可以通过将dict_values 转换为list 来解决它:

total_paid = list(Payment.objects.aggregate(Sum('amount')).values())[0] or 0 # the or 0 is required in case the query is an empty query set.

前面的代码避免使用'column_name__sum' 作为键,但如果你更喜欢字典方式:

total_paid = Payment.objects.aggregate(Sum('amount'))['amount__sum'] or 0

效率方面,我用我手头的一些数据做了个测试,好像用字典键比较快:

In [9]: %timeit total = Pledge.objects.filter(user=user, group__isnull=True).aggregate(Sum('amount'))['amount__sum'] or 0
3.13 ms ± 25.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [10]: %timeit total = list(Pledge.objects.filter(user=user, group__isnull=True).aggregate(Sum('amount')).values())[0] or 0
3.22 ms ± 61.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

在可读性方面,我认为@mehmet的解决方案是最好的,我也测试了它的效率:

In [18]: %timeit Pledge.objects.filter(user=user, group__isnull=True).aggregate(sum=Sum('amount'))['sum'] or 0
3.22 ms ± 124 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

【讨论】:

【参考方案5】:

(仅在使用十进制字段时才有用) 如果您使用小数,则将键值存储在新变量中并将其转换为浮点数。我认为这是最简单的方法

total_paid = Payment.objects.all.aggregate(Sum('amount'))
# output: 'amount__sum':Decimal('0000.000000')
tp=total_paid['amount__sum']
new_total_paid=float(tp)

【讨论】:

【参考方案6】:

100% 你可以通过这种技术解决你的需求

from django.db.models import Sum

sum_count = Payment.objects.aggregate(Sum('amount'))
totalAmonut = sum_count['Qty__sum']

【讨论】:

以上是关于Django聚合:仅求和返回值?的主要内容,如果未能解决你的问题,请参考以下文章

Elasticsearch聚合初探——metric篇

Elasticsearch聚合初探——metric篇

Django Aggregation - 试图返回两个值

具有多个查找和管道的聚合仅返回最后一个元素

ES之五:ElasticSearch聚合

ElasticSearch聚合aggs入门