Django计算模型字段时间差总和返回空结果无报错如何解决
问题诊断
- 聚合逻辑使用错误:你当前使用
annotate()是为每个Portfolio对象计算其关联项目的设计时长总和,返回的是Portfolio查询集,而非单个总时长值。如果你需要统计全量项目的总设计时长,应该直接对Project表做聚合,使用aggregate()而非annotate() - 模板取值错误:你传给模板的
design_time是查询集对象,直接调用.design_time属性不存在,自然返回空结果 - 冗余查询链路:从
Portfolio跨多对多关系查询Project计算总和,完全可以直接在Project表完成,还能避免多对多关联带来的重复计数问题(比如同一个项目属于多个Portfolio会被重复计算)
修改方案
1. 视图代码调整
如果你的需求是统计所有项目的总设计时长,修改get_context_data方法如下:
首先确保你已经导入了所需依赖:
from django.db.models import F, Sum, ExpressionWrapper from django.db.models.fields import DurationField
然后修改视图逻辑:
class DashView(generic.ListView): context_object_name = 'project_list' template_name = 'index.html' queryset = Project.objects.all() def get_context_data(self, **kwargs): context = super(DashView, self).get_context_data(**kwargs) # 直接对Project表做聚合计算总时长 total_result = Project.objects.aggregate( total_design_time = ExpressionWrapper( Sum(F('design_end') - F('design_start')), output_field=DurationField() ) ) context['design_time'] = total_result['total_design_time'] return context
2. 模板代码调整
现在design_time已经是直接的时长值,直接输出即可:
<h4>{{ design_time }}</h4>
如果需要仅展示天数,可以调用days属性:
<h4>总设计时长:{{ design_time.days }}天</h4>
补充说明
如果你的需求是统计每个Portfolio对应关联项目的总设计时长,则视图修改为:
def get_context_data(self, **kwargs): context = super(DashView, self).get_context_data(**kwargs) context['portfolio_list'] = Portfolio.objects.annotate( design_time = ExpressionWrapper( Sum(F('projects__design_end') - F('projects__design_start')), output_field=DurationField() ) ) return context
模板循环取值即可:
{% for portfolio in portfolio_list %} <h4>组合{{ portfolio.id }}总设计时长:{{ portfolio.design_time.days }}天</h4> {% endfor %}
内容的提问来源于stack exchange,提问作者GeorgeS
相关产品推荐
相关产品推荐

