Opened 4 years ago

Closed 4 years ago

#31930 closed New feature (wontfix)

Using a builtin callable as a default arg for JSONField.

Reported by: Stuart Buckingham Owned by: nobody
Component: Migrations Version: 3.1
Severity: Normal Keywords: Migrations default field callable
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

I have a JSONField that I need to apply a default dictionary to. As per the documentation, I am avoiding passing the mutable dictionary to the default field. This is done by instead passing the copy method to the default argument like such:

default_dict = {'some_key': 'some value'}

class MyModel(models.Model):
    my_field = models.JSONField(default=default_dict.copy)

When applying makemigrations, this is failing because of the following condition in django.db.migrations.serializer.FunctionTypeSerializer:

if self.value.__module__ is None:
    raise ValueError("Cannot serialize function %r: No module" % self.value)

I can get around this by defining a callable that returns a copy, but I think this is adding unnecessary syntax and makes it harder to read:

class ADict(dict):
    def __call__(self):
        return self.copy()

default_dict = ADict({'some_key': 'some value'})

class MyModel(models.Model):
    my_field = models.JSONField(default=default_dict)

Change History (1)

comment:1 by Mariusz Felisiak, 4 years ago

Resolution: wontfix
Status: newclosed
Summary: Using a builtin callable as a default arg for JSONFieldUsing a builtin callable as a default arg for JSONField.
Type: BugNew feature

When applying makemigrations, this is failing because of the following condition in django.db.migrations.serializer.FunctionTypeSerializer:

copy() can’t be serialized by migrations because it's not in module’s top-level scope, see documentation for other caveats.

I can get around this by defining a callable that returns a copy, but I think this is adding unnecessary syntax and makes it harder to read:

You can omit this restriction by using a function (see docs):

def my_field_default():
    return {'some_key': 'some value'}

class MyModel(models.Model):
    my_field = models.JSONField(default=my_field_default)
Note: See TracTickets for help on using tickets.
Back to Top