[Django]-Django Admin: JSONField default empty dict wont save in admin

31πŸ‘

βœ…

  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})
πŸ‘€banxi1988

7πŸ‘

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)

2πŸ‘

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

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

πŸ‘€Ruben

2πŸ‘

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)
πŸ‘€tessafyi

1πŸ‘

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.

πŸ‘€nurettin

0πŸ‘

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='|')
πŸ‘€alamyudi

0πŸ‘

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

Leave a comment