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

如何使用Django ORM实现嵌套Group By 统计各出版社对应图书出版数量

解决方法

问题原因

你当前的代码query_set.values('publisher', 'title').annotate(count=Count('title'))是按照publisher和title两个字段联合分组,最终得到的是每条数据对应一个「出版社+书名」的独立统计项,没有做按出版社的二次聚合,所以无法直接输出嵌套结构。

推荐实现方案(全版本兼容)

先通过ORM拿到基础统计数据,再用Python做二次组装,逻辑清晰且兼容所有Django版本:

from django.db.models import Count

# 获取出版社+书名维度的统计数据
stat_data = query_set.values("publisher", "title").annotate(count=Count("title")).order_by("publisher")

# 组装为目标嵌套格式
res = []
current_publisher = None
pub_info = None

for item in stat_data:
    pub = item["publisher"]
    title = item["title"]
    cnt = item["count"]
    # 遇到新出版社则创建新条目
    if pub != current_publisher:
        if pub_info:
            res.append(pub_info)
        pub_info = {"publisher": pub, "titles": {}}
        current_publisher = pub
    pub_info["titles"][title] = cnt
# 补充最后一个出版社的条目
if pub_info:
    res.append(pub_info)

运行后得到的res就完全符合你需要的格式。

高版本Django简化方案(Django >= 4.0)

如果使用Django 4.0及以上版本,可以借助JSONBAgg和JSONObject在数据库层面完成部分聚合,减少Python层的遍历逻辑:

from django.db.models import Count, F, JSONBAgg
from django.db.models.functions import JSONObject

res = list(
    query_set.values("publisher", "title")
    .annotate(count=Count("title"))
    .values("publisher")
    .annotate(
        titles=JSONBAgg(
            JSONObject(key=F("title"), value=F("count"))
        )
    )
    .values("publisher", "titles")
)
# 仅需一步转换把数组转成字典
for item in res:
    item["titles"] = {i["key"]: i["value"] for i in item["titles"]}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 01:18:03