在 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.6
from 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 框架中的多个对象?

尝试覆盖django rest框架中的update方法,以在更新后返回整个查询集

序列化程序中的django rest框架更新方法,实例不会立即保存

完全迷失:在 Django Rest 框架中使用序列化器和更新的多对多

Django REST 框架:使用相关字段创建/更新对象

python django-rest-framework 3.3.3 更新嵌套序列化程序