Django 1.9 Сохраненный словарь JSONfield возвращает unicode вместо
Мы только что обновили до Django 1.9 и переместили вещи на свое встроенное JSONfield, которое мы используем для хранения словаря. Тем не менее, когда я пытаюсь читать данные из него, он возвращает unicode словаря.
My JSONfield определяется как:
class SmsInfo(models.Model):
[...]
json = JSONField(default=dict)
Данные записываются на него:
params = dict(request.POST)
SmsInfo.objects.create([...], json=params, [...])
Далее читается следующим образом:
incoming_smsses = SmsInfo.objects.select_related('game').defer('game__serialized').filter([...])
В какой момент:
print incoming_smsses[0].json.__class__
возвращает
<type 'unicode'>
вместо dict, которого я ожидаю, и мой код падает, потому что он не может искать какие-либо ключи.
Я застрял на этом совсем немного, и я не могу понять, почему это происходит не так. Я использовал literal_eval как обходное решение, которое теперь возвращает юникод в dict. Это работает сейчас, но я бы лучше занялся этим в источнике!
Почему мой словарь включен в Юникод здесь?
Ответы
Ответ 1
Я только что прошел обновление от стороннего JSONField до собственного Postgres JSONField и нашел через psql, что тип столбца все еще text
.
Итак, на psql, подтвердите свой тип столбца:
\d+ table_name
И измените столбец, если он все еще текст:
ALTER TABLE table_name ALTER COLUMN column_name TYPE jsonb USING column_name::jsonb;
Ответ 2
Как было предложено erickw в комментариях, это было зарегистрировано как ошибка: https://code.djangoproject.com/ticket/27675
Если раньше вы использовали django-jsonfield
, между ними существует конфликт, поэтому, как показывает вышеприведенная ошибка, решение состоит в том, чтобы полностью удалить и переделать файлы миграции приложения, которое использует jsonfield.
В этом случае, по-видимому, вы также захотите удалить django-jsonfield
.
Ответ 3
Я использую Django 1.11 и postgres 11.4.
Передача списка 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')
Я предполагаю, что для диктов это должно сработать
И моя модель:
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()
Ответ 4
Как указывает @stelios, это ошибка с django-jsonfield
, которая не совместима с нативной версией.
Или:
- удалить
django-jsonfield
(если это больше не требуется в качестве зависимости проекта, вы можете проверить с помощью pipdeptree
), или
- обновите до
django-jsonfield >= 1.3.0
, поскольку проблема теперь закрыта, а исправление объединено.
Ответ 5
Похоже, это связано с хранилищем БД. Тем не менее этот JSONField действует как валидатор для правильного форматирования JSON.
Однако вы можете взломать и загрузить dict из этой возвращенной строки юникода.
Попробуйте следующее:
import json
data = json.loads(incoming_smsses[0].json)
Затем вы можете получить к нему доступ как ИМП. dict.
Ответ 6
Вам нужно использовать собственные postgres JSONField
from django.contrib.postgres import fields
class Some_class(models.Model):
json = fields.JSONField()