6

My class looks like this:

class Foo(models.Model):
  known_by = JSONField()

My data looks like this

{ "known_by" : [
                {'by':'name1', 'value':['def']},
                {'by':'name2', 'value':['bar']}
               ]
}

Is there any way for me to enforce that the Jsonfield needs to follow the format of by,value[] dict. I know how to do this using serialiazers

Any other cleaner way to enforce this(in the model definition itself)? Thanks

suprita shankar
  • 1,554
  • 2
  • 16
  • 47
  • 1
    try this http://stackoverflow.com/questions/9686409/how-to-store-a-dictionary-in-a-django-database-models-field – badiya Apr 19 '17 at 17:07

3 Answers3

4

You can add a validator to the model field, like this:

 class Foo(models.Model):
     known_by = ArrayField(JSONField(max_length=100), size=4, validators=[a_json_array_validator])

And the validator is:

def a_json_array_validator(value):
    if any([not is_json_valid(entry) for entry in value]):
        raise ValidationError(
            _('%(value) is not a valid json'),
            params={'value': value},
         )

(The actual json validation is up to you) ;-) Note that validators receive python objects so its actually a dict.

Joaquin
  • 81
  • 4
  • 1
    No this won't work. First of all - One cannot have a `JSONField` inside of a `ArrayField` it will throw an error! – suprita shankar Apr 21 '17 at 22:44
  • 1
    I was assuming the provided code worked. You can use the JSONField only and use a validator. The point was not to provide an exact solution but an idea. Cheers. – Joaquin Apr 22 '17 at 14:44
  • 1
    Hey! Thank you for pointing it out. I edited it. In fact I implemented similar kind of code you have up there 2 weeks back. But now I was wondering if there is a better way :) Thank you for taking time to reply. Sorry if I was rude. – suprita shankar Apr 22 '17 at 18:32
1

You could implement it this way:

from django.db import models

class Bar(models.Model):
    by = models.CharField()
    value = models.ArrayField()


class Foo(models.Model):
    known_by = models.ForeignKey(Bar, on_delete=models.CASCADE)
raiderrobert
  • 653
  • 5
  • 16
0

Why not just override the save method to do the enforcement?

class Foo(models.Model):
    known_by = JSONField()

    def save(self, *args, **kwargs):
        # begin validation code

        # end validation code
        if valid:
            super(Model, self).save(*args, **kwargs)
        else:
            # something else, maybe http error code?
Morifen
  • 126
  • 1
  • 7