System check identified some issues but I can't.

When I migrate or run the testserver, I get this following complaint.

System check identified some issues:

WARNINGS:
contentmanager.ContentElement.text: (fields.E010) JSONField default should be a callable instead of an instance so that it’s not shared between all field instances.
HINT: Use a callable instead, e.g., use dict instead of {}.

Here’s the referenced field:
text = JSONField(default=dict(settings.MULTITEXT_CHOICES))

And here’s settings.MULTITEXT_CHOICES:

    # (*Language*, _('*Display Name*')),
    (MULTITEXT_LANGUAGES['ENGLISH'], 'English'),
    (MULTITEXT_LANGUAGES['GERMAN'], 'German'),
]

So from my understanding, dict() is a callable. However I’m using it on a list of lists. So, does that mean, that I’m creating an independent instance of dict which points to the same values, as the list of lists? Is that why I get the complaint?
The values in the settings.py don’t ever change during runtime which makes me think, that I can ignore the warning.

When you call dict() in the model definition, you get a single instance returned, that is then shared between all instances, which isn’t likely what you want.

Since it’s not a plain dictionary you need, you can’t just pass dict (Note no () so the callable, not the returned dictionary when you call it, with the ())

Instead, you can create a function that just makes and returns the dict(...) call you’ve got currently, this creating a new dictionary each time, so instanced won’t share the default.

Hope that helps.

1 Like

Thanks, that helps. Maybe you can answer another question on that regard: the method I would write couldn’t live inside the class of the model, because then it doesn’t exist when it is needed. I had this case before and so I just placed the method in front of the class, but then it is a classless static method. Is that the right place for the method to be or should it be somewhere else?

I think it might be one of those few cases where a lambda would be appropriate…
default=lambda:dict(settings.MULTITEXT_CHOICES)

(On the phone so I can’t test that. You might need ())

Otherwise you’d just put it in a named function.

To add to @carltongibson’s sage advice, and only to address your specific question, I will say that yes, in this case, under these circumstances, it’s perfectly acceptable for that method to exist outside a class. (I am not one of those that believes in “Classes everywhere”. I also tend to work under the general principle that any solution that works is a good solution.)

Ken

Hey Carlton,

unfortunately a lambda is not the solution. I got an error when trying to migrate.

Migrations are just Python files containing the old definitions of your models - thus, to write them, Django must take the current state of your models and serialize them out into a file. While Django can serialize most things, there are some things that we just can’t serialize out into a valid Python representation…
Django can serialize the following: Any function or method reference… in module’s top-level scope
Django cannot serialize: Lambdas
Source

So a function it will be.

Ah, super. There you are then. Use a function it is. :+1: