如何在Django ListView中获取关联模型字段的聚合总和?
解决Django中按Item统计item_sold总值并在ListView展示的问题
先帮你捋捋当前代码里的问题,再一步步给出解决方案~
首先你用When的方式不对哦,When是用来做条件筛选求和的,而你现在只是要统计每个Model_Item关联的所有Model_ItemTransaction里item_sold的总和,完全不需要用到它,直接用Sum关联反向字段就可以搞定。
1. 修正ListView的查询逻辑
先把views.py里的get_queryset改成下面这样:
from django.db.models import Sum from django.db.models.functions import Coalesce class View_Item(ListView): model = Model_Item # 记得替换成你实际的模板路径 template_name = "items/item_list.html" def get_queryset(self): # 先调用父类的get_queryset获取基础查询集 queryset = super().get_queryset() # 关联反向交易记录,统计item_sold的总和 # 用Coalesce处理空值:如果没有交易记录,总和显示0而不是None queryset = queryset.annotate( total_sold=Coalesce(Sum('model_itemtransaction__item_sold'), 0.0) ) return queryset
2. 优化模型的可读性(可选但推荐)
你的外键反向关系默认是model_itemtransaction_set,名字有点长,建议给Model_ItemTransaction的外键加个related_name,让代码更清晰:
class Model_ItemTransaction(models.Model): # 添加related_name="transactions",方便后续调用 item = models.ForeignKey(Model_Item, to_field="item_name", related_name="transactions") item_sold = models.FloatField(null=True, blank=True) def __unicode__(self): # 原代码返回self.item会输出对象,改成转成字符串显示商品名更友好 return str(self.item)
改完后,annotate里的求和代码就可以写成更直观的:
total_sold=Coalesce(Sum('transactions__item_sold'), 0.0)
3. 在模板中展示统计值
最后在你的ListView模板里,直接循环object_list,调用每个item的total_sold字段就行:
{% for item in object_list %} <div class="item-card"> <h3>{{ item.item_name }}</h3> <p>累计销售总量:{{ item.total_sold }}</p> </div> {% endfor %}
为什么原代码不行?
你之前写的Sum(When(model_itemtransaction__item_sold))是错误用法:When必须配合condition和then参数使用,比如用来统计“某个时间段内的销量”这种有条件的场景,而你现在是要所有关联交易的总和,直接用Sum关联反向字段就足够啦。
内容的提问来源于stack exchange,提问作者Fxs7576
相关产品推荐
相关产品推荐

