Поле обновления Array / Jsonb: psycopg2.ProgrammingError - PullRequest
0 голосов
/ 16 ноября 2018

Использование Django 2.1 / python 3.6 Я хочу обновить поле в существующей модели.

Поле имеет следующий тип:

from django.contrib.postgres.fields import (
    ArrayField,
    JSONField
)
waypoints = ArrayField(
    JSONField(
        default=list,
        null=True,
        blank=True
    ),
    size=None,
    null=True,
    blank=True
)

И поле будет хранить данные в формате:

[
    {'lat': 63.123334, 'lon': 13.433918, 'date': '2018-08-23 11:00:00', 'direction': 123, 'rpm': 0},
    {'lat': 42.315119, 'lon': -3.213883, 'date': '2018-08-12 09:15:00', 'direction': 95.45, 'rpm': 3998},
    {'lat': 51.763023, 'lon': 7.376109, 'date': '2018-08-19 03:30:00', 'direction': 45.76, 'rpm': 7823}
]

Я прекрасно осознаю тот факт, что это не очень хорошая практика, и что лучшим способом было бы использовать внешний ключ с другой моделью, но мои руки связаны.

Мой код:

scheduler_response = {
    "result": {
        "time": 23,
        "total_consumption": 98117,
        "waypoints": [
            {
                "lat": 42.315119,
                "lon": -3.213883,
                "date": "2018-08-12 09:15:00",
                "direction": 95.45,
                "rpm": 3998,
                "cumulative_consumption": 0
            },
            {
                "lat": 51.763023,
                "lon": 7.376109,
                "date": "2018-08-19 03:30:00",
                "direction": 45.76,
                "rpm": 7823,
                "cumulative_consumption": 44298
            },
            {
                "lat": 63.123334,
                "lon": 13.433918,
                "date": "2018-08-23 11:00:00",
                "direction": 123,
                "rpm": 0,
                "cumulative_consumption": 98117
            }
        ]
    }
}
scheduler_waypoints = scheduler_response.get('result').get('waypoints')
job_updates = {}
job_updates['waypoints'] = scheduler_waypoints
print(type(job_updates['waypoints']))
job_updates['total_consumption'] = scheduler_response.get('total_consumption')
serialized_job = JobSerializer(active_job, data=job_updates, partial=True)

if serialized_job.is_valid():
    print('is_valid')
    print(serialized_job.validated_data)
    serialized_job.save()
    print('FINISHED')

Мой вывод на терминал выглядит следующим образом:

<class 'list'>
is_valid
OrderedDict([('total_consumption', None), ('waypoints', [{'lat': 42.315119, 'lon': -3.213883, 'date': '2018-08-12 09:15:00', 'direction': 95.45, 'rpm': 3998}, {'lat': 51.763023, 'lon': 7.376109, 'date': '2018-08-19 03:30:00', 'direction': 45.76, 'rpm': 7823}, {'lat': 63.123334, 'lon': 13.433918, 'date': '2018-08-23 11:00:00', 'direction': 123, 'rpm': 0}])])

Обратите внимание, что, хотя сериализатор проверен, сериализатор не может быть сохранен («FINISHED» не печатается).

Я получаю сообщение об ошибке:

Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/django/db/backends/utils.py", line 85, in _execute
    return self.cursor.execute(sql, params)
psycopg2.ProgrammingError: column "waypoints" is of type jsonb[] but expression is of type text[]
LINE 1: ...d" = 1, "total_consumption" = NULL, "waypoints" = ARRAY['{"l...
                                                            ^
HINT:  You will need to rewrite or cast the expression.

Почему это? Что я делаю не так (кроме неиспользования внешнего ключа и другой модели)?

1 Ответ

0 голосов
/ 16 ноября 2018

Ответом для всех, кто хочет совершить подобную атрофичность, является использование JSONBField в вашей модели, а не JSONField внутри поля списка, вот изменения, которые я сделал в моей модели:

from django.contrib.postgres.fields.jsonb import JSONField as JSONBField
class Job(models.Model):
    waypoints = JSONBField(
        default=list,
        null=True,
        blank=True
    )

Код, вызывающий сериализатор, работает нормально.

...