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聚合:仅求和返回值?的主要内容,如果未能解决你的问题,请参考以下文章