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

Django中如何通过ORM从JSONField指定路径查询并转为列表?

Django ORM 查询 JSONField 指定路径并转换为列表

问题背景

我有一个包含JSONField的Django模型:

class SDReport(models.Model):
    summary = models.JSONField()

summary字段的示例数据如下:

{
    "1": {
        "stm": {
            "1": []
        },
        "non_stm": {
            "1": ["3419250", "3205437"]
        }
    },
    "2": {
        "stm": {
            "1": []
        }
    }
}

需要通过ORM从路径'1' > non_stm > '1'中查询数据(预期结果为["3419250", "3205437"],默认值为[])。

我已经尝试了以下代码实现查询:

SDReport.objects.annotate(lst=RawSQL("(summary->'1'->'non_stm'->>'1')", ())).first()

但查询得到的lst是字符串类型,请问能否在查询阶段就将其转换为列表?


解决方案

方法1:改用->替代->>(适配PostgreSQL)

你之前用的->>会返回文本类型,改用->直接获取JSONB类型,Django的JSONField会自动将其反序列化为Python列表:

from django.db.models import RawSQL

report = SDReport.objects.annotate(
    lst=RawSQL("summary->'1'->'non_stm'->'1'", ())
).first()

# 此时 report.lst 为列表类型
print(type(report.lst))  # <class 'list'>

方法2:使用Cast函数转换类型(通用兼容)

如果需要兼容更多场景,可通过Django的Cast函数将字符串结果强制转换为JSON类型:

from django.db.models import Cast, JSONField
from django.db.models.expressions import RawSQL

report = SDReport.objects.annotate(
    lst=Cast(
        RawSQL("summary->'1'->'non_stm'->>'1'", ()),
        output_field=JSONField()
    )
).first()

print(type(report.lst))  # <class 'list'>

方法3:Django 4.0+ 原生JSON路径查询

Django 4.0及以上版本支持直接通过双下划线进行JSON路径查询,无需手写RawSQL,代码更简洁:

from django.db import models

report = SDReport.objects.annotate(
    lst=models.F('summary__1__non_stm__1')
).first()

print(type(report.lst))  # <class 'list'>

内容的提问来源于stack exchange,提问作者Альберт Александров

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 05:15:36