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,提问作者Альберт Александров
相关产品推荐
相关产品推荐

