[Fixed]-Proper declaration of an empty Django PostgreSQL JSONField default value in migration file

53๐Ÿ‘

โœ…

A callable is an object x that can be called, hence x() is valid, and will not raise an error because it is not callable (although there can be errors during the call, for example because the function somewhere yields an error).

dict() is actually completely equivalent to {}, that is not a callable, since {}(), will not result in constructing anything. But dict itself on the other hand is a reference to the dict class, and if we call it, we construct a new dict. So we should write it like:

# no brackets! We do not make a call, but pass the callable
foo = JSONField(default=dict)

So we do not call the dict class, we pass a reference to the class, and such classes are callable: if you call them, you typically construct a new instance (although this behavior can be changed).

Passing the callable is of vital importance here, since otherwise Django will each time use a reference to the same dictionary. As a result changes to one of the dictionaries will change the others that change the reference. If you store the dictionary and reload it, then this will be a different dictionary, but as long as you constructed two models, during the same Python run, these would be the same objects.

If you however pass a function, the function will be called, and thus produce two different objects, both empty dictionaries. But changes to the first dictionary will not reflect in the second one.

The same holds if you for instance would want to initialize a JSON field with a dictionary that contains data, instead of writing default={'a': 4}, one has to define it like:

def default_somemodel_dict():
    return {'a': 4}

class SomeModel(models.Model):
    foo = JSONField(default=default_somemodel_dict)

Leave a comment