Django Model实现增量累计总和时所有记录返回总数值问题排查
你当前的total_hours方法每次调用都会对全表所有Hours记录执行聚合求和,所以所有实例调用返回的都是全表总小时数,自然不会得到逐行递增的运行累计值。
场景1:保留实例方法写法
如果需要在单个实例上直接调用方法获取累计值,可以按你指定的排序规则(通常用主键id、创建时间等),筛选出排序顺序在当前记录之前(含当前记录)的所有数据再求和,示例代码如下:
from django.db import models from django.db.models import Sum class Hours(models.Model): name = models.CharField(max_length=200) hours = models.DecimalField(max_digits=6, decimal_places=2) def running_total_hours(self): # 示例按主键id升序排序累计,如需其他排序规则替换过滤条件即可 return Hours.objects.filter(id__lte=self.id).aggregate(total=Sum('hours'))['total']
场景2:批量查询时更高效的实现
如果是批量查询列表时要获取每条记录的累计值,更推荐用Django的窗口函数在查询时直接注解结果,避免每条记录都单独触发一次数据库查询,性能更高:
from django.db.models import Window, Sum, F # 按id升序排序,同时注解累计小时数字段 hours_queryset = Hours.objects.order_by('id').annotate( running_total = Window( expression=Sum('hours'), order_by=F('id').asc() ) ) # 遍历查询结果直接获取累计值 for hour_obj in hours_queryset: print(f"{hour_obj.name}:当前小时数{hour_obj.hours},累计小时数{hour_obj.running_total}")
注意:累计值的计算依赖明确的排序规则,如果你需要按其他字段(比如创建时间、业务编号等)排序累计,替换上述代码中的
id为对应字段即可。
内容的提问来源于stack exchange,提问作者Umar Milanzi Snr
相关产品推荐
相关产品推荐

