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

Django+Postgres使用JSONBAgg实现多字段聚合生成字典列表

解决方法

你之前的写法问题在于直接向JSONBAgg传入多个字段时,聚合函数会将所有字段值扁平化压入数组,无法实现「每个关联B对象对应一个字典」的结构。正确做法是先将每个B对象的多个字段拼装为单个JSON对象,再对这些JSON对象执行聚合。


适用Django 3.2及以上版本

直接使用内置的JSONObject函数构造单条JSON结构:

from django.contrib.postgres.aggregates import JSONBAgg
from django.contrib.postgres.functions import JSONObject

queryset = A.objects.annotate(
    # 每个JSONObject对应1个关联的B对象,键名可自定义
    b_list = JSONBAgg(
        JSONObject(
            amount = 'b__amount',
            c_id = 'b__c__id'
            # 需返回其他B字段/关联C字段,在这里添加键值对即可
        )
    )
).values('name', 'b_list')

返回的b_list字段即为你需要的字典列表格式,示例返回结构:

{
    "name": "A对象名称",
    "b_list": [
        {"amount": 10, "c_id": 1},
        {"amount": 20, "c_id": 2}
    ]
}

低版本Django兼容方案

如果使用的Django版本低于3.2没有JSONObject,可以用RawSQL配合json_build_object实现同样效果:

from django.contrib.postgres.aggregates import JSONBAgg
from django.db.models import RawSQL

queryset = A.objects.annotate(
    b_list = JSONBAgg(
        RawSQL(
            "json_build_object('amount', %s, 'c_id', %s)",
            ('b__amount', 'b__c__id')
        )
    )
).values('name', 'b_list')

可选优化:空关联返回空列表

默认情况下如果A对象没有关联的B对象,JSONBAgg会返回null,如果需要统一返回空列表,可以搭配Coalesce处理:

from django.contrib.postgres.aggregates import JSONBAgg
from django.contrib.postgres.functions import JSONObject
from django.db.models import Value, Coalesce
from django.contrib.postgres.fields import JSONField

queryset = A.objects.annotate(
    b_list = Coalesce(
        JSONBAgg(
            JSONObject(amount='b__amount', c_id='b__c__id')
        ),
        Value([], output_field=JSONField())
    )
).values('name', 'b_list')

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 21:24:01