Django中如何使用QuerySet.update直接操作JSONField无需循环遍历
报错原因
Django的QuerySet.update()原生不支持直接用__双下划线语法更新JSON字段的嵌套键,双下划线的JSON路径语法仅支持查询过滤场景,所以你尝试用bar__some_key作为更新字段时会抛出FieldDoesNotExist错误。
解决方案
所有方案均直接在数据库层面执行,无需将模型实例加载到内存,性能和原生update操作一致。
1. 批量给缺失some_key的字段设置默认值
Django 4.2+ 通用写法(兼容PostgreSQL/MySQL等主流数据库)
from django.db.models import Value from django.db.models.fields.json import JsonSet Foo.objects.exclude(bar__has_key="some_key").update( bar=JsonSet("bar", ["some_key"], Value({"x": "y"})) )
低版本Django适配写法
根据你使用的数据库选择对应函数:
- PostgreSQL 使用
jsonb_set函数:
from django.db.models import F, Value, Func from yourapp.models import JSONField # 替换为你实际导入JSONField的路径 Foo.objects.exclude(bar__has_key="some_key").update( bar=Func( F("bar"), Value("some_key"), Value({"x": "y"}, output_field=JSONField()), function="jsonb_set" ) )
- MySQL 使用
JSON_SET函数:
from django.db.models import F, Value, Func from yourapp.models import JSONField Foo.objects.exclude(bar__has_key="some_key").update( bar=Func( F("bar"), Value("$.some_key"), Value({"x": "y"}, output_field=JSONField()), function="JSON_SET" ) )
2. 批量删除所有bar字段中的some_key键
Django 4.2+ 通用写法
from django.db.models.fields.json import JsonRemove Foo.objects.filter(bar__has_key="some_key").update( bar=JsonRemove("bar", ["some_key"]) )
低版本Django适配写法
- PostgreSQL 使用
jsonb_remove_path函数:
from django.db.models import F, Value, Func Foo.objects.filter(bar__has_key="some_key").update( bar=Func( F("bar"), Value(["some_key"]), function="jsonb_remove_path" ) )
- MySQL 使用
JSON_REMOVE函数:
from django.db.models import F, Value, Func Foo.objects.filter(bar__has_key="some_key").update( bar=Func( F("bar"), Value("$.some_key"), function="JSON_REMOVE" ) )
内容的提问来源于stack exchange,提问作者Vedran Šego
相关产品推荐
相关产品推荐

