You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Django Queryset的annotate/aggregate实现顺序累计求和?

实现Queryset的累计总量计算(随排序同步变化)

需求说明

现有Rice模型如下:

class Rice(models.Model):
    quantity = models.DecimalField(...)

查询所有对象并遍历输出quantity时得到:

5
7
9
10

需要实现到每个对象为止的累计总量,期望输出:

5
12
21
31

且要求累计逻辑随Queryset的排序规则同步变化。


数据库层面实现(推荐,高效且符合要求)

利用Django的Window窗口函数结合Sum聚合函数,直接在数据库层面计算累计值,支持动态排序。

代码示例

from django.db.models import Sum, Window, F
from django.db.models.functions import WindowFrame

# 按id升序排序并计算累计量,可替换order_by中的字段实现排序变化
rices = Rice.objects.annotate(
    cumulative_quantity=Window(
        expression=Sum('quantity'),
        order_by=F('id').asc(),  # 修改这里的排序字段,累计顺序同步改变
        frame=WindowFrame(start=None, end=0)  # 累计范围:从第一行到当前行
    )
)

# 遍历输出结果
for rice in rices:
    print(rice.cumulative_quantity)

说明

  • 该方法依赖数据库对窗口函数的支持,适用于PostgreSQL 9.4+、MySQL 8.0+、SQL Server 2012+等主流现代数据库。
  • order_by参数是核心:只要修改这里的排序规则(比如换成F('created_at').desc()),累计逻辑就会自动适配新的排序顺序。

兼容老数据库的Python层面实现

如果你的数据库不支持窗口函数,可在Python层面遍历计算累计值:

代码示例

# 先指定排序规则,累计顺序随此排序同步变化
rices = Rice.objects.order_by('id')

total = 0
for rice in rices:
    total += rice.quantity
    print(total)
    # 可选:给对象临时添加累计属性,方便后续使用
    rice.cumulative_quantity = total

说明

  • 该方法兼容所有数据库,但数据量较大时,性能不如数据库层面的实现。
  • 排序规则通过order_by指定,修改排序字段后累计逻辑自动同步。

内容的提问来源于stack exchange,提问作者Srijan113

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 15:36:59