Home > Blockchain >  expanding dict model field in django
expanding dict model field in django

Time:06-30

I need a way to be able to enter an unspecified number of arbitrary, integer values with an auto-incrementing key into a dictionary in a django model.

It would need to look, or at least function, like this:

{
  "1":6,
  "2":10,
  "3":0,
  ...
  "n":42
}

I'm hoping there will be a simple solution like:

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

Unfortunately, I know that doesn't work and wouldn't function how the comment suggests, but it would need to act like that for the end-user.

I've looked through the docs and the only workaround I found there was using models.JSONField(), but that requires you to type out the dict yourself, which is not ideal. Another possible way that I found would be to separate the dict and the k-v pairs, linking them with a foreign key, but I couldn't quite figure out how to integrate it and it seemed very messy even if I could.

If you need any more info, just let me know.

Any help is much appreciated, thanks.

Edit: Also to note, I am currently using the admin page to enter items at the moment, but it will eventually be handled from the frontend (react), just in case that changes anything.

CodePudding user response:

Option 1, solution with 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()

Unfortunately for this method, you will have to do some work everytime you want to add another value to the list:

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()

Option 2, use related table:

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}"

The good thing for this method is that you do not have to think about the other, previous values stored before - just add a new child for this parent:

parent = AJsonModelWithChild.objects.create(name="Two")
parent.save()
child = GrowingChild.objects.create(value=100, parent=parent)
child.save()
  • Related