如何子类化 modelform(从模型扩展额外字段)?
我有一个模型和一个表单:
class MyModel(models.Model):
field_foo = models.CharField(_("Foo"), max_length=50)
field_bar = models.IntegerField(_("Bar"))
class MyFormOne(forms.ModelForm):
class Meta:
model=MyModel
fields = ('field_foo', )
widgets = {'field_foo': forms.TextInput(attrs={'size': 10, 'maxlength': 50}),}
我想要再创建一个表单 MyFormTwo
,这个表单要在原有表单的基础上增加一个字段 field_bar
。我的目的是为了避免在第二个表单中重复声明 field_foo
这个控件(遵循DRY原则),而且也不想在 MyFormOne
中重复列出字段(实际上,字段的数量比上面这个简单的例子要多得多)。
我应该怎么定义 MyFormTwo
呢?
3 个回答
0
这个代码片段有点老了,但它解释了我唯一能让多重继承工作的方法。说实话,这个方法看起来挺丑陋的。
http://djangosnippets.org/snippets/703/
关于这个问题,还有一个开放的工单:https://code.djangoproject.com/ticket/7018
3
我不确定这个方法是否有效(我还没有在Django的表单或模型上测试过),不过如果有效的话请告诉我。
class MyModel(models.Model):
field_foo = models.CharField(_("Foo"), max_length=50)
field_bar = models.IntegerField(_("Bar"))
class MyFormOne(forms.ModelForm):
class Meta:
model=MyModel
fields = ('field_foo', )
widgets = {'field_foo': forms.TextInput(attrs={'size': 10, 'maxlength': 50}),}
class MyFormTwo(MyFormOne):
class Meta(MyFormOne.Meta):
fields = MyFormOne.Meta.fields + ('field_foo2',)
widgets = MyFormOne.Meta.widgets
# Add new fields as a dictionary
widgets.update({'field_foo2': forms.TextInput(attrs={'size': 10, 'maxlength': 50}),)
# Or add them one by one
widgets['field_foo3'] = forms.TextInput(attrs={'size': 10, 'maxlength': 50})
再说一次,我也不知道这是否能帮到你。请告诉我你得到的结果。
4
你不需要完全声明整个小部件,只需要修改那些不同的属性就可以了。或者,如果你在实际代码中有自定义的小部件,我会选择以下两种方法:
- 创建一个自定义的模型字段类,这个类默认使用那个小部件,如果这是一个通用的情况,那么在表单类中它就会“自动”工作。
- 如果只是针对表单的特定情况(而不是模型特定),那么我会在表单类中明确声明表单字段,而不是在Meta中,这样继承就会以简单明了的方式应用。
但是对于默认的小部件(带有自定义属性),我会尝试以下方法:
class MyModel(models.Model):
field_foo = models.CharField(_("Foo"), max_length=50)
field_bar = models.IntegerField(_("Bar"))
class MyFormOne(forms.ModelForm):
class Meta:
model=MyModel
fields = ('field_foo', )
def __init__(*args, **kwargs):
super(MyFormOne, self).__init__(*args, **kwargs)
self.fields['field_foo'].widget.attrs['size'] = 10
# max_length should already be set automatically from model
# TextInput is also default widget for CharField
class MyFormTwo(MyFormOne):
class Meta:
model=MyModel
fields = MyFormOne.Meta.fields + ('field_foo2',)
def __init__(*args, **kwargs):
super(MyFormTwo, self).__init__(*args, **kwargs)
self.fields['field_foo2'].widget.attrs['size'] = 10