Django 聚合查询:仅返回 Sum 的值?

40

我有一个支付值列表,想要显示支付的总额。我已经使用聚合和 Sum 来计算这些值的总和。问题是,我只想打印出总值,但是聚合会打印出:{'amount__sum': 480.0} (其中480.0是添加的总值)。

在我的视图中,我有:

    from django.db.models import Sum

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

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

And to show the value on the page, I have a mako template with the following:


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

如何使它显示480.0而不是{'amount__sum': 480.0}


1
aggregate(sum = Sum('amount')) 这个怎么样?在模板中可以这样使用 ${total_paid.sum} - karthikr
6个回答

63

我不相信有一种方法可以只获取值。

您可以在模板中使用 ${{ 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}},但它没有效果。但是在视图中调用它非常有效! - Stephen
@jproffitt,你能举个例子吗?当聚合执行成功时,你不会有一个键为“amount__sum”的字典。 - lmiguelvargasf
@lmiguelvargasf 你说得对。不需要使用 .get。我已经修改了我的回答。 - jproffitt

34
给它一个名称,然后请求它:
total_paid = Payment.objects.all.aggregate(sum=Sum('amount'))['sum']

应该更易读,不需要进行转换。


1
这是最短和最简洁的答案。 - dogewang
2
只是提醒一下,请不要使用内置函数的名称,比如sum - vishes_shell

25
aggregate() 方法返回一个字典。如果你知道你只会返回一个单一的键值对,你可以使用 .values()[0]
Python 2中:
total_paid = Payment.objects.aggregate(Sum('amount')).values()[0]
在Python 3中,(感谢@lmiguelvargasf) 这将需要变为:
total_paid = list(Payment.objects.aggregate(Sum('amount')).values())[0]

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


2
这也是我首选的解决方案。在Python3中,values()已经更改以返回视图而不是列表。将values()的返回值通过list()传递可以使此解决方案起作用。 - Taylor D. Edmiston
1
我同意@TaylorEdmiston的观点,这段代码在Python 3上无法运行。我已经添加了一个解决方案的答案。 - lmiguelvargasf
谢谢@lmiguelvargasf。为了帮助未来的其他人,我刚刚提交了一个社区编辑,添加了Python 3的代码行。我相信在同行批准后,它将对其他人可见。 - Taylor D. Edmiston

3

在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)

0

使用这种技术,你可以100%解决你的需求。

from django.db.models import Sum

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

0

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

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

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