简体   繁体   English

Django 1.9 JSONfield存储字典改为返回unicode

[英]Django 1.9 JSONfield stored dictionary returns unicode instead

We've just upgraded to Django 1.9 and moved things to its built-in JSONfield, which we use to store a dictionary. 我们刚刚升级到Django 1.9并将其移动到内置的JSONfield,我们用它来存储字典。 However, when I try to read data from it, it returns unicode of the dictionary instead. 但是,当我尝试从中读取数据时,它会返回字典的unicode。

My JSONfield is defined as: 我的JSONfield定义为:

class SmsInfo(models.Model):
    [...] 
    json = JSONField(default=dict)

Data is written to it by: 数据通过以下方式写入:

params = dict(request.POST)
SmsInfo.objects.create([...], json=params, [...])

It is later read in this way: 稍后会以这种方式阅读:

incoming_smsses = SmsInfo.objects.select_related('game').defer('game__serialized').filter([...])

At which point: 在这一点上:

 print incoming_smsses[0].json.__class__

returns 回报

<type 'unicode'> 

instead of the dict I am expecting and my code crashes because it can't look up any keys. 而不是我期待的字典,我的代码崩溃,因为它无法查找任何键。

I've been stuck on this for quite a bit, and I can't figure out why this is going wrong. 我已经坚持了很多,我无法弄清楚为什么会出错。 I've used literal_eval as a workaround for now, which turns the unicode back into a dict. 我现在使用literal_eval作为解决方法,它将unicode变回dict。 That works for now, but I'd rather tackle this at the source! 这暂时有效,但我宁愿在源头解决这个问题!

Why is my dictionary being turned to unicode here? 为什么我的字典在这里转为unicode?

I just went through upgrading from a third-party JSONField to the native postgres JSONField and found through psql that the column type is still text . 我刚刚从第三方JSONField升级到本机postgres JSONField,并通过psql发现列类型仍然是text

So on psql, confirm your column type: 所以在psql上,确认您的列类型:

\d+ table_name

And alter the column if it's still text: 如果列仍然是文本,则更改列:

ALTER TABLE table_name ALTER COLUMN column_name TYPE jsonb USING column_name::jsonb;

As suggested by erickw in comments, this has been filed as a bug: https://code.djangoproject.com/ticket/27675 正如erickw在评论中所建议的那样,这已被提交为一个错误: https ://code.djangoproject.com/ticket/27675

If you happened to use django-jsonfield before, there is a conflict between them, thus as the bug above suggests, the solution is to completely delete and remake the migration files of the app which uses the jsonfield. 如果您之前碰巧使用过django-jsonfield ,则它们之间存在冲突,因此如上面的错误所示,解决方案是完全删除并重新创建使用jsonfield的应用程序的迁移文件

In that case, apparently you would like to uninstall django-jsonfield as well. 在这种情况下,显然你也想卸载django-jsonfield

I'm using Django 1.11 and postgres 11.4. 我正在使用Django 1.11和postgres 11.4。

Passing list of python dicts to JSONField worked for me: 将python dicts列表传递给JSONField对我有用:

data_python = []
for i in range(3):
    entry = {
        'field1': value1,
        'field2': 999,
        'field3': 'aaaaaaaaaa',
        'field4': 'never' 
    }
    data_python.append(entry)
MyModel.objects.create(data=data_python, name='DbEntry1')

My guess is that for dicts this should work as well 我的猜测是,对于dicts,这应该也可以

And my model is: 我的模型是:

class MetersWithNoReadings(models.Model):
    created_datetime = models.DateTimeField(auto_now_add=True)
    updated_datetime = models.DateTimeField(auto_now=True)
    name = models.CharField(max_length=25)
    data = JSONField()

As @stelios points out, this is a bug with django-jsonfield which is not compatible with the native version. 正如@stelios所指出的,这是django-jsonfield一个错误,它与本机版本不兼容。

Either: 或者:

  • uninstall django-jsonfield (if it is no longer required as a project dependency, you can check with pipdeptree ), or 卸载django-jsonfield (如果不再需要它作为项目依赖项,可以使用pipdeptree进行检查),或者
  • upgrade to django-jsonfield >= 1.3.0 since the issue is now closed and the fix merged. 升级到django-jsonfield >= 1.3.0因为问题现已关闭并且修复程序已合并。

Seems related to DB storage here. 这里似乎与数据库存储有关。 Still this JSONField acts as a validator for proper JSON formatting. 这个JSONField仍然可以作为正确JSON格式的验证器。

However, you can hack around and load a dict from this returned unicode string. 但是,您可以通过此返回的unicode字符串来破解并加载dict。

Try as follow : 尝试如下:

import json
data = json.loads(incoming_smsses[0].json)

Then you can access it as a dict IMO. 然后你可以作为词典IMO访问它。

You need to use native postgres JSONField 您需要使用本机postgres JSONField

from django.contrib.postgres import fields

class Some_class(models.Model):
    json = fields.JSONField()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM