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

Django中使用F()访问JSONField嵌套字段触发JSONDecodeError的原因

Django JSONField使用F('bb__p1')报错的原因解析

问题场景

定义的Django模型:

class Helo(models.Model):
    id = models.IntegerField(primary_key=True)
    aa = models.JSONField(null=True)
    bb = models.JSONField(null=True)

示例数据:

idaabb
1{"p1":11 "p2": 22}{"p1": 33, "p2": 44}

执行以下查询时出现json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)错误:

test = Helo.objects.filter(aa__p1__gte=F('bb__p1'))
test.count()

但执行下面的代码却无报错:

test = Helo.objects.filter(aa__p1__gte=F('bb'))
test.count()

原因解析

Django的F()表达式核心是直接引用数据库层面的字段名,它不支持解析ORM为JSONField封装的__嵌套键查询语法。

当你写F('bb__p1')时,Django会把bb__p1当作一个完整的数据库字段名去查找,但你的表中不存在该字段,数据库返回无效内容,后续JSON解析环节就会抛出解码错误。

而F('bb')是直接引用bb这个JSONField字段本身,数据库会返回该字段的完整JSON字符串,因此不会触发解码错误(但这个查询逻辑不符合需求,本质是拿aa里的p1值和整个bb的JSON字符串做比较)。

解决思路

要实现JSONField嵌套键之间的比较,需要借助Func类直接调用数据库的JSON处理函数,以PostgreSQL为例,可以用KeyTextTransform提取嵌套值:

from django.db.models import F
from django.db.models.functions import KeyTextTransform

test = Helo.objects.annotate(
    bb_p1=KeyTextTransform('p1', 'bb')
).filter(aa__p1__gte=F('bb_p1'))
test.count()

通过annotate先提取bb字段里的p1值并命名为bb_p1,再用F()引用这个注解字段,就能实现预期的查询逻辑。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 16:27:14