Before a model is instantiated, it's fields are an actual instance of a Field
subclass (such as BooleanField
). Direct assignment of a value does not work yet. Only in the Model's __init__
method do they get replaced with their actual value.
That's why your first method doesn't work: you try to assign a value before calling super(CyclesMaterial, self).__init__(*args, **kwargs)
, and override the BooleanField
instance. The model no longer sees gen_description
as a model field, but just as a regular object attribute.
I have just tested your second solution, and these are my results:
# No value set
>>> c = CyclesMaterial()
>>> c.gen_description
False
# Value set to `True`
>>> c = CyclesMaterial(gen_description=True)
>>> c.gen_description
True
# Value set to `False`
>>> c = CyclesMaterial(gen_description=False)
>>> c.gen_description
False
That is exactly the behavior I expect, and if I understood your question correctly, the behavior you want. If gen_description
is not set, it won't be in kwargs
, and kwargs.set_default('gen_description', False)
will set it to False
. If it is set, it will be in the kwargs
, and it's value will be preserved and set directly on the model.
EDIT:
If you want the default value to change in your admin interface or in other forms, you'll have to manually override it in your forms. ModelForm
s are generated based on the class definition, and you can't change the field's options without changing them for all superclasses as well. So you'll have to change the initial
value for the forms, overriding the generated default:
# either this:
form = CyclesMaterialForm(initial={'gen_description': False})
# or this:
class CyclesMaterialForm(forms.ModelForm):
gen_description = forms.BooleanField(_('Generate description'),
help_text=_("If checked, the description will be automatically "
"generated from content. Uncheck if you want to manually "
"set a custom description."), initial=False, required=False)
Then change all instances of your form to use either the first solution, or to be an instance of CyclesMaterialForm
as provided in the second solution.