在 django rest 框架中更新 JSONField
Posted
技术标签:
【中文标题】在 django rest 框架中更新 JSONField【英文标题】:Updating JSONField in django rest framework 【发布时间】:2016-08-09 09:45:32 【问题描述】:我目前已经熟悉在 django rest-framework 中使用 JSONField,但是我找不到任何直接的方法来更新存储的 json 中的键。过滤 JSONField 的方法有很多,取决于它的内部键,但似乎无法从已存储的 JSONField 中更改、更新或删除键。但似乎 postgres 可以像 this answer 解释的那样对 json 键进行一些修改。
是否有任何功能可以对 JSONFields 进行修改。如果没有任何直接命令可以执行此操作,那么实现 JSONField 修改的最佳方法是什么?
编辑:
例如,如果我有这样的模型:
class Thing(models.Model):
name = models.CharField()
properties = JSONField()
在properties
中我存储了一个这样的json:
"color" : "red",
"size" : "large",
"cost" : 1234
然后我想通过使用 django 命令将颜色更改为“绿色”。
【问题讨论】:
您能否举例说明您正在寻找什么样的更新。最简单的方法是读入python,修改成字典,保存。 @serg 请查看编辑说明。 【参考方案1】:thing = Thing.objects.get(name="...")
thing.properties['color'] = 'green'
thing.save()
【讨论】:
对不起,我现在无法检查您的答案,但我会尽快检查并给您反馈。 @serg 我检查了你的答案,我认为thing
中的properties
不像字典或json(它是unicode
),所以你需要一些中间操作才能将其更改为字典然后再次保存它。 django 似乎不支持这个,所以我必须像你在这里写的那样做。
应该是字典,你用的是最新的Django,Postgres db 9.4+?属性字段的值是什么,json 作为字符串(unicode)?另外,如果您可以转到 postgres 控制台并检查您的属性字段类型是否为jsonb
。
对不起,我的回答迟了,你说得对,在当前版本中它是一本字典,尽管在某些情况下它不是一本我觉得奇怪的字典,但在大多数情况下是一本字典。
有没有办法用.update()
做到这一点?【参考方案2】:
您可以在这里找到更好的解决方案 https://django-postgres-extensions.readthedocs.io/en/latest/json.html
【讨论】:
最后那个“__”没有帮助。【参考方案3】:对于您的模型:
class Thing(models.Model):
name = models.CharField()
properties = JSONField()
如果您需要更新一堆条目,您可以执行以下操作:
Thing.objects.update(
properties=RawSQL("jsonb_set(properties, 'color', 'green', true)", [])
)
color: green
将被插入,如果不存在。
欢迎来到PostgreSQL docs,了解更多关于jsonb_set
的信息。
【讨论】:
【参考方案4】:下一个语法对我有用,
Django==2.2.19 Postgres==12.0.6from django.db.models.expressions import RawSQL
Thing.objects.update(properties=RawSQL("""jsonb_set(properties, \'"name"\',\'"name value"\', true)""", []))
【讨论】:
【参考方案5】:来自@tarasinf 和@Vladius001 的jsonb_set
方法也适用于Django 的Func expression。
Thing.objects.update(
properties=Func(
F("properties"),
Value(["color"]),
Value("green", JSONField()),
function="jsonb_set",
)
)
【讨论】:
这是更简洁的更新方式。 请注意,update 方法会立即提交,因此事务回滚将不起作用。至少这是我的经验。以上是关于在 django rest 框架中更新 JSONField的主要内容,如果未能解决你的问题,请参考以下文章
尝试覆盖django rest框架中的update方法,以在更新后返回整个查询集
序列化程序中的django rest框架更新方法,实例不会立即保存