Domanda

I have a model that inherits from Mezzanine's "Displayable" model that itself inherits from the "Slugged" model. In the Slugged model there are these lines:

gen_description = models.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."), default=True)

For the model i did create i want the default behaviour to not create a description automatically. Overriding the field itself is - of course - not going to work.

My first guess was this:

def __init__(self,*args,**kwargs):
        self.gen_description = False
        super(CyclesMaterial,self).__init__(*args,**kwargs)

but no luck. I did not really expect this to work, but still gave it a try.

Trying to find a solution i found this question. So i tried to do this in my model:

def __init__(self,*args,**kwargs):
        kwargs.setdefault('gen_description', False)
        super(CyclesMaterial,self).__init__(*args,**kwargs)

but it's not working.

What to do to achieve what i want to? Is it possible?

È stato utile?

Soluzione

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. ModelForms 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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top