#python #django #psycopg2
#python #django #psycopg2
Вопрос:
Я сталкиваюсь с проблемами при использовании new django.db.models.JSONField
, когда кажется, что столбец возвращается из базы данных, уже десериализованной, т.Е. Уже a dict
. Модель снова пытается десериализовать значение, что приводит к исключению.
TypeError: the JSON object must be str, bytes or bytearray, not dict
Это исключение генерируется из json.loads
вызова в from_db_value
методе определения JSONField
класса.
def from_db_value(self, value, expression, connection):
if value is None:
return value
try:
return json.loads(value, cls=self.decoder)
except json.JSONDecodeError:
return value
Мы запускаем postgres, и столбец определен в базе данных как json
, т.е. нет jsonb
. Похоже, что у моих моделей, в которых есть столбцы, которые являются jsonb
, нет этой ошибки.
Похоже, у меня нет проблемы, когда столбец в модели сохраняется как строка. Только когда столбец является dict
.
class MyModel(models.Model):
data = models.JSONField()
m1 = MyModel(data=json.dumps({"key": "value"})
m1.save()
m1.refresh_from_db()
m2 = MyModel(data={"key": "value")
m2.save()
m2.refresh_from_db() # Exception thrown here
Я предполагаю, что в этом случае он кодируется дважды. Все, что вызывает его декодирование в a dict
, декодирует его, а затем декодируется в a dict
на уровне модели.
>>> import json
>>> a = json.dumps({"key": "value"})
>>> a
'{"key": "value"}'
>>> json.dumps(a)
'"{\"key\": \"value\"}"'
Я даже пытался придерживаться определенного поля Postgres, и у него та же проблема. В нашей базе данных уже есть записи, которые вызвали эту проблему, и поэтому я уже не могу сохранить столбец со значением json.dumps
. Я даже не думаю, что это все равно устраняет проблему.
Зависимости
Django==3.1.3
psycopg2==2.8.6
Комментарии:
1. Это
JSONField
потому, что он обрабатывает JSON автоматически. Итак, нет необходимости загружать или сбрасывать. Если вы действительно хотите сделать это вручную, используйте текстовое поле.2. Я это понимаю. Как я уже сказал, я не хочу в
json.dumps
столбец. Пожалуйста, перечитайте то, что я написал.3. Может быть полезно: code.djangoproject.com/ticket/32135 Цитата: «Похоже, что вы используете json вместо типа данных jsonb в своей базе данных, что не поддерживается».
4. Да, я думал, что суть проблемы, по-видимому, заключается
json
в vsjsonb
. Я не знал, что они действительно не поддерживаютjson
. Он работал нормально, пока я не обновился до 3.1. У меня сложилось впечатление, что именно тогда была отменена своего рода подразумеваемая поддержка. Похоже, нам придется перенести этот столбец вjsonb
5. В моем случае я использовал неуправляемую таблицу Django, поэтому, когда я создавал
json
поле в своей базе данных, я не знал об этом ограничении. Итак, мое решение состояло в том, чтобы просто изменить наjsonb
.