Django Admin: JSONField default empty dict wont save in admin

Question:

in my model defn i have

from django.contrib.postgres.fields import JSONField
.....
.......
.........

media_data=JSONField(default=dict)

I created a default admin

When i attempt to save without touching the field, i get a this field is required error.

field is required

It looks like a form validation issue because I can programatically save the model instance from code without issue.

Why is this happening?
have i missed something silly?

Asked By: w–

||

Answers:

Depending on your requirements, consider to use blank and/or null.

media_data=JSONField(blank=True, null=True)

Answered By: Ruben

This caused problems for me recently, though with django-mysql rather than postgres and in a custom ModelForm rather than the admin interface.

I ended up overriding my model’s save() method:

from django_mysql.models import JSONField

class yourModel(model):
    media_data=JSONField(default=dict, blank=True)

    def clean(self, *args, **kwargs):
        if self.media_data is None:
            self.media_data = "{}"

    def save(self, *args, **kwargs):
        self.clean()
        super().save(*args, **kwargs)
Answered By: tessafyi
  1. What happening.
    when dive into the source code. we can see the following call stack:
    1) form.is_valid() 
       ->form.full_clean()
        -->form._clean_fields()
         ---> self.cleand_data[name] = field.clean(value)
    2) field.clean(value)
        -> self.to_python(value)
        -> self.validate(value)

when look into the source code ,you can find that,it’s mainly because the empty_values check.

# These values, if given to validate(), will trigger the self.required check.
EMPTY_VALUES = (None, '', [], (), {})

as you can see the empty dict {} is as an empty value for JSONField. so it will raise Error.

  1. What can we do?
    the Solution would be to customize the models.JSONField and forms.JSONField like below.

forms.py

from django.contrib.postgres import forms

class MyJSONField(forms.JSONField):
    empty_values = [None, "", [], ()]

db/fields.py

class MyJSONField(JSONField):
    def formfield(self, **kwargs):
        from ..forms import MyJSONField

        return super().formfield(**{"form_class": MyJSONField, **kwargs})
Answered By: banxi1988

i have similar problem previously. adding required=False in your form field will solve the problem.

class YourForm(forms.ModelForm):
    media_data = SimpleArrayField(JSONField(), required=False, widget=forms.Textarea, delimiter='|')
Answered By: alamyudi

I faced the same issue. How did I fix it? In order to bypass the validation process that excludes {} as valid json, I added both blank=True and null=True. For example: models.JSONField(blank=True, null=True, default=dict)

I had the same issue and similarly I created a new Field based class but instead of using a form and model field I just made one that tweaked the innards of the formfield after it gets instantiated.

class CustomJSONField(JSONField):
empty_values = [None, '', [], ()]

def formfield(self, **kwargs):
    result = super().formfield(**kwargs)
    result.empty_values = self.empty_values
    return result
Answered By: Christian Jensen

This works in django 4.1 admin screen:

class YourModel(Model):
    your_field = JSONField(default=list, null=False, blank=True)

I can leave the text field as [] and the admin screen saves it fine.

Answered By: nurettin