Расширение поля модели dict в django
Мне нужен способ ввести неопределенное количество произвольных, целочисленных значений с автоматически увеличивающимся ключом в словарь в модели django.
Он должен выглядеть или, по крайней мере, функционировать следующим образом:
{
"1":6,
"2":10,
"3":0,
...
"n":42
}
Я надеюсь, что будет простое решение, такое как:
class Foo(models.Model):
title = models.CharField(max_length=100)
dictOfInts = {
models.AutoField(): models.IntegerField,
models.AutoField(): models.IntegerField,
models.AutoField(): models.IntegerField
...
# it would start with just one and automatically add more k-v pairs as nessary
}
#other fields ect
def __str__(self):
return self.title
К сожалению, я знаю, что это не работает и не будет функционировать так, как предлагается в комментарии, но это должно действовать так для конечного пользователя.
Я просмотрел документацию и единственным обходным решением, которое я нашел, было использование models.JSONField()
, но это требует, чтобы вы сами набирали dict, что не идеально. Другим возможным способом, который я нашел, было бы разделить dict и k-v пары, связав их внешним ключом, но я не смог понять, как это интегрировать, и это кажется очень грязным, даже если бы я смог.
Если вам нужна дополнительная информация, дайте мне знать.
Любая помощь будет очень признательна, спасибо.
Edit: Также хочу отметить, что в настоящее время я использую страницу администратора для ввода элементов, но в конечном итоге он будет обрабатываться из фронтенда (react), на всякий случай, если это что-то изменит.
Вариант 1, решение с JSONField:
class AJsonModel(models.Model):
name = models.CharField(null=True, max_length=255)
data = models.JSONField(null=True)
def __str__(self):
return f"A list of {[n for n in self.data]}"
data = [10, 20, 30, 40, 50]
dict_data = {k:v for (k, v) in enumerate(data, 1)}
m = AJsonModel.objects.create(name="One", data=dict_data)
m.save()
К сожалению для этого метода, вам придется выполнять некоторую работу каждый раз, когда вы хотите добавить еще одно значение в список:
c = AJsonModel.objects.get(id=1)
values = list(c.data.values())
values.append(60)
c.data = {k:v for (k, v) in enumerate(values, 1)}
c.save()
Вариант 2, использовать связанную таблицу:
class AJsonModelWithChild(models.Model):
name = models.CharField(null=True, max_length=255)
def __str__(self):
return f"{self.name}"
class GrowingChild(models.Model):
value = models.IntegerField(default=0)
parent = models.ForeignKey(AJsonModelWithChild, on_delete=models.CASCADE)
def __str__(self):
return f"{self.id}: {self.value}"
Преимущество этого метода в том, что вам не нужно думать о других, предыдущих значениях, сохраненных ранее - просто добавьте нового ребенка для этого родителя:
parent = AJsonModelWithChild.objects.create(name="Two")
parent.save()
child = GrowingChild.objects.create(value=100, parent=parent)
child.save()