如何在Django中覆盖继承的modelfield的默认值?

时间:2014-03-20 19:18:45

标签: django inheritance mezzanine

我有一个继承自Mezzanine“可显示”模型的模型,该模型本身继承自“Slugged”模型。在Slugged模型中有以下几行:

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)

对于我创建的模型,我希望默认行为不自动创建描述。当然,覆盖这个领域本身并不会起作用。

我的第一个猜测是:

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

但没有运气。我真的没想到这会起作用,但还是试了一下。

试图找到我找到this question的解决方案。所以我试着在我的模型中这样做:

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

但它不起作用。

如何实现我想要的目标?有可能吗?

1 个答案:

答案 0 :(得分:3)

在模型实例化之前,它的字段是Field子类的实际实例(例如BooleanField)。直接赋值不起作用。只有在模型的__init__方法中,它们才会被实际值替换。

这就是为什么你的第一个方法不起作用的原因:你在调用super(CyclesMaterial, self).__init__(*args, **kwargs)之前尝试分配一个值,并覆盖BooleanField实例。模型不再将gen_description视为模型字段,而是将其视为常规对象属性。

我刚刚测试了你的第二个解决方案,这些是我的结果:

# 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

这正是我期望的行为,如果我理解你的问题,你想要的行为。如果未设置gen_description,则不会kwargs,而kwargs.set_default('gen_description', False)会将其设置为False。如果已设置,则它将在kwargs中,并且它的值将被保留并直接在模型上设置。

修改

如果您希望在管理界面或其他表单中更改默认值,则必须在表单中手动覆盖它。 ModelForm是根据类定义生成的,您无法更改字段的选项,也无需为所有超类更改字段的选项。因此,您必须更改表单的initial值,覆盖生成的默认值:

# 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)

然后更改表单的所有实例以使用第一个解决方案,或者更改为第二个解决方案中提供的CyclesMaterialForm实例。