Django Annotate Sum

时间:2018-05-09 05:45:24

标签: python django python-3.x

我正在尝试为查询集中包含多行的列获取一个简单的总和。我的直接问题是(a)如何设置get_queryset()以包含列的总和,以及(b)如何在模板中访问该元素?关注this问题:

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

提供了两个答案 - 一个使用.aggregate()方法,我不相信会返回一个查询集和.annotate()方法,我认为该方法会将一个项目附加到查询集。

所以,我希望以下内容会在此视图中的对象列表中添加另一个项目:

#views.py
def get_queryset(self):
    # generate table and filter down to a subquery.
    queryset = ItemPrice.objects.filter(<some_filter>)
    # sum the price for each row in the subquery.
    queryset = queryset.annotate(totals=Sum('price'))
    return queryset

然后在模板中,我将能够像这样迭代对象列表:

#template.html
{% for item in object_list %}
    {{ item }}
{% endfor %}

期望其中一个项目(最后一项?)为price_sum,并且余额可以price_sum.price进行访问。

但是,当我在模板中添加以下内容时,我会得到每个订单项的价格 - 没有总结。

{% for item in object_list %}
    {{ item.totals }}
{% endfor %}

但是,我无法访问该项目。我不知道问题是get_queryset()的视图修改还是它在模板中?

2 个答案:

答案 0 :(得分:1)

如果要将数据添加到模板

queryset = ItemPrice.objects.filter(<your_filter>)
totals = queryset.aggregate(sum=Sum('price').get('sum')

context  = {
    'object_list': queryset,
    'totals: totals,
}
render(request, '<name_of_your_template>.html', context)

并在您的模板中

{% for item in object_list %}
    # price of item
    {{ item.price }}
{% endfor %}
# total price
{{ totals }}

答案 1 :(得分:0)

如果你愿意的话:

ItemPrice.objects.filter(<some_filter>).annotate(totals=Sum('price'))

总计将始终与'价格'相同

annotate(关于Sum)使用如下:

如果您有这些型号:

class ItemPrice( models.Model ):
    price = models.DecimalField ( max_digits = 8, decimal_places=2 )
    other_model = models.ForeignKey(
          to=OtherModel, 
          related_name="item_prices", 
          on_delete=models.SET_NULL
    )

# related_name - if I set related_name I can use like this
# other_model_object.item_prices.all() - this code return all 
# ItemPrices with other_model_id=other_model_object.id

class OtherModel(models.Model):
    some_field = models.CharField(max_lenght=256)

并且您希望所有具有外键的ItemPrices的价格都应该使用这些代码:

queryset = OtherModel.objects.annotate(
       total_prices=Sum('item_prices__price')
).filter(<your_filters>)

之后你可以使用:

for obj in queryset:
    print(obj.total_prices)

或者,如果您需要所有价格的总和,您应该使用汇总

ItemPrices.objects.aggregate(all_sum=Sum('price'))

此代码返回dict(或类似的东西,我不记得确切) 像这样

{'all_sum': 1250}

all_sum - 数据库中表中所有对象的总和