Невозможно ввести 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,
]