Невозможно ввести json в админке django

В моей модели есть следующее поле -

data_fields = ArrayField(models.JSONField(null=True, blank=True), blank=True, null=True)

Для того чтобы проверить это, я ввел следующее в поле data_field в админке django -

[{"key": "name", "label": "Name"}, {"key": "amount", "label": "Amount"}]

Но я получаю ошибку, говорящую

Item 1 in the array did not validate: Enter a valid JSON.
Item 2 in the array did not validate: Enter a valid JSON.
Item 3 in the array did not validate: Enter a valid JSON.
Item 4 in the array did not validate: Enter a valid JSON.

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

Почему это происходит и как это исправить?

Это одна из многих причин не использовать ArrayField или JSONField в первую очередь [django-antipatterns]. Насколько я знаю, ArrayField не очень хорошо поддерживаются ни в базах данных, ни в Django, и это приводит к всевозможным проблемам с запросами и формами.

При этом, почему бы просто не использовать JSONField [Django-doc], в конце концов, список - это JSON-блоб, поэтому использование:

data_fields = models.JSONField(null=True, blank=True, default=list)

Но все же, если структура фиксирована, как, например, у JSON-блоба, я бы посоветовал использовать inline:

class Parent(models.Model):
    pass


class ParentDataField(models.Model):
    parent = models.ForeignKey(
        Parent, related_name='data_fields', on_delete=models.CASCADE
    )
    key = models.CharField(max_length=128)
    label = models.CharField(max_length=128)

На самом деле, мы даже можем гарантировать, что для одного и того же parent, key встречается не более одного раза:

class Parent(models.Model):
    pass


class ParentDataField(models.Model):
    parent = models.ForeignKey(
        Parent, related_name='data_fields', on_delete=models.CASCADE
    )
    key = models.CharField(max_length=128)
    label = models.CharField(max_length=128)

    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields=('parent', 'key'), name='unique_key_per_parent'
            )
        ]

и затем работать с инлайном:

from django.contrib import admin


class ParentDataFieldInline(admin.TabularInline):
    model = ParentDataField


class ParentAdmin(admin.ModelAdmin):
    inlines = [
        ParentDataFieldInline,
    ]
Вернуться на верх