为啥 Django 将 postgres JSONField 值作为字符串返回?
Posted
技术标签:
【中文标题】为啥 Django 将 postgres JSONField 值作为字符串返回?【英文标题】:Why does Django return postgres JSONField value as string?为什么 Django 将 postgres JSONField 值作为字符串返回? 【发布时间】:2017-08-03 22:18:57 【问题描述】:环境:
Django 1.10.6 psycopg2 2.7.1 通过 Homebrew 在 macOS Sierra 上安装 PostgreSQL 9.6.2 通过 Homebrew 安装的 Python 3.6.0示例模型:
from django.db import models
from django.contrib.postgres.fields import JSONField
class Foo(models.Model):
data = JSONField()
当我尝试创建一个对象时,一切都按预期工作:
from myapp.models import Foo
x = Foo()
x.data = 'key1': 'value1'
x.save()
查询按预期工作:
Foo.objects.filter(data__key1='value1').count()
# 1
但是,当我尝试从对象中检索该数据时,.data
属性的值是一个字符串:
from myapp.models import Foo
x = Foo.objects.get(id=1)
x.data
# '"key1": "value1"'
type(x.data)
# str
我希望在这里得到一个字典。尝试保存对象时,问题会递归地变得更糟
x.save()
x = Foo.objects.get(id=1)
x.data
# '"\\"key1\\": \\"value1\\""'
x.save()
x = Foo.objects.get(id=1)
x.data
# '"\\"\\\\\\"key1\\\\\\": \\\\\\"value1\\\\\\"\\""'
【问题讨论】:
这不应该发生。你能展示你的完整模型吗?您是否有任何验证器、自定义保存方法或附加到保存事件的任何信号? 我开始从项目中安装的其他应用程序向后工作,发现罪魁祸首是这个应用程序github.com/jjkester/django-auditlog。当我从 MIDDLEWARE 和 INSTALLED_APPS 中删除它时,一切都按预期工作。进一步看,该项目需要 django-jsonfield 并且两者之间一定存在一些不兼容 事实上它已经是该项目中的一个未解决问题github.com/jjkester/django-auditlog/issues/71 【参考方案1】:原来你不能在同一个项目中使用 django-jsonfield 和 Django 的原生 JSONField,否则你会遇到问题中描述的奇怪行为
https://bitbucket.org/schinckel/django-jsonfield/issues/57/cannot-use-in-the-same-project-as-djangos
【讨论】:
【参考方案2】:对我来说,问题是数据库是从备份创建的,列类型设置为text
,而它本应为json
或jsonb
。
清除所有无效的 json,然后使用以下内容更改列类型:
ALTER TABLE t ALTER COLUMN j TYPE jsonb USING j::text::jsonb;
(感谢https://***.com/a/28076909/2362877)
【讨论】:
以上是关于为啥 Django 将 postgres JSONField 值作为字符串返回?的主要内容,如果未能解决你的问题,请参考以下文章
使用 postgres 在 Django 中高效存储 Json
Django 和 postgres - 在模型字段中将数据存储为 json 的缺点
将 json 作为 celery 任务的一部分插入 postgres
使用 Django 从 Postgres 导出 JSON 时结果不一致