Django JSONField внутри ArrayField

У меня проблема с вставкой в ​​поле с использованием ArrayField с внутренним JSONField.

models.py

locations = ArrayField(JSONField(null = True,blank = True), blank=True, null = True)

Вставить

location_arr = [{"locations" : "loc1","amount":Decimal(100.00)},{"locations" : "loc2","amount":Decimal(200.25)}]
instance.locations = location_arr
instance.save()

Когда я это сделаю, я получил

"location" столбца имеет тип jsonb [], но выражение имеет тип text []

LINE 1:... d "= 2517," locations "= ARRAY ['{" loc...

Подсказка: вам нужно будет переписать или применить выражение.

Итак, я попытался сбросить его, используя:

import json
location_arr = [{"locations" : "loc1","amount":Decimal(100.00)},{"locations" : "loc2","amount":Decimal(200.25)}]
instance.locations = json.dumps(location_arr)
instance.save()

то я получил это

LINE 1:... d "= 2517," locations "= '[{" loc ":...

ПОДРОБНОЕ ОПИСАНИЕ:" [" должно вводить явно заданные размеры массива.

Я использую:

  • Django 1.9
  • Python 2.7
  • Postgres 9.4.10
  • psycopg2 2.6.2

Ответ 1

Массивы

Прежде всего, давайте внимательно посмотрим на этот важный текст из документа Postgresql Arrays.

Совет: массивы не являются наборами; поиск определенных элементов массива может быть признаком неправильного проектирования базы данных. Попробуйте использовать отдельную таблицу со строкой для каждого элемента, который будет элементом массива. Это будет легче для поиска, и, вероятно, лучше масштабируется для большого количества элементов.

Большую часть времени вы не должны использовать массивы.

JSONB

JSONB доступен в Django как тип JSONField. Это поле является более масштабируемым и гибким, чем поля массива, и его можно искать более эффективно. Однако, если вы все время будете искать внутри полей JSONB, приведенное выше утверждение о массивах в равной степени верно и для JSONB.

Теперь, что у вас есть в вашей системе? Массив, который содержит поле JSONB. Это катастрофа, ожидающая случиться. Пожалуйста, нормализуйте ваши данные.

резюмировать

так когда использовать ArrayField?

В редких случаях, когда вам не нужно искать в этом столбце, и вам не нужно использовать этот столбец для объединения.

Ответ 2

Я столкнулся с тем же сценарием. Вот как я его решил

models.py

from django.contrib.postgres.fields.jsonb import JSONField as JSONBField
location = JSONBField(default=list,null=True,blank=True)

Вставка

model_object.location = [{"locations" : "loc1","amount":Decimal(100.00)},{"locations" : "loc2","amount":Decimal(200.25)}]

Обновление

model_object.location.append({"locations" : "loc1","amount":Decimal(100.00)})
model_object.save()

Это работало для меня в  Django - 2.0.2  Postgres - 9.5  psycopg2 - 2.7.4  python - 3.4.3

Ответ 3

Вы можете обойти эту проблему, используя JSONField в качестве типа поля столбца со list в качестве корневого элемента.

from django.contrib.postgres.fields import JSONField
class MyDBArray(models.Model):
    array_data = models.JSONField(default=list)

my_db_array = MyDBArray(array_data=[1, 2, 3])
my_db_array.save()

Вам необходимо проверить в методе save что поле array_data самом деле похоже на список.