你可以使用多重继承又名mixins,分解出 Form 和 ModelForm 中使用的字段。
class SwallowFormFields:
airspeed_velocity = forms.IntegerField( ... )
is_migratory = forms.BooleanField( ... )
class AfricanSwallowForm(forms.ModelForm, SwallowFormFields):
class Meta:
model = AfricanBird
class EuropeanSwallowForm(forms.Form, SwallowFormFields):
pass
UPDATE:
由于这不适用于 Django 元编程,因此您需要创建一个自定义__init__
构造函数将继承的字段添加到对象的字段列表中,或者您可以在类定义中显式添加引用:
class SwallowFormFields:
airspeed_velocity = forms.IntegerField()
is_migratory = forms.BooleanField()
class AfricanSwallowForm(forms.ModelForm):
airspeed_velocity = SwallowFormFields.airspeed_velocity
is_migratory = SwallowFormFields.is_migratory
class Meta:
model = AfricanSwallow
class EuropeanSwallowForm(forms.Form):
airspeed_velocity = SwallowFormFields.airspeed_velocity
is_migratory = SwallowFormFields.is_migratory
UPDATE:
当然,您不必将共享字段嵌套到类中 - 您也可以简单地将它们定义为全局变量......
airspeed_velocity = forms.IntegerField()
is_migratory = forms.BooleanField()
class AfricanSwallowForm(forms.ModelForm):
airspeed_velocity = airspeed_velocity
is_migratory = is_migratory
class Meta:
model = AfricanSwallow
class EuropeanSwallowForm(forms.Form):
airspeed_velocity = airspeed_velocity
is_migratory = is_migratory
UPDATE:
好吧,如果你真的想最大限度地干燥,你必须选择元类.
所以你可以这样做:
from django.forms.models import ModelForm, ModelFormMetaclass
from django.forms.forms import get_declared_fields, DeclarativeFieldsMetaclass
from django.utils.copycompat import deepcopy
class MixinFormMetaclass(ModelFormMetaclass, DeclarativeFieldsMetaclass):
def __new__(cls, name, bases, attrs):
# default __init__ that calls all base classes
def init_all(self, *args, **kwargs):
for base in bases:
super(base, self).__init__(*args, **kwargs)
attrs.setdefault('__init__', init_all)
# collect declared fields
attrs['declared_fields'] = get_declared_fields(bases, attrs, False)
# create the class
new_cls = super(MixinFormMetaclass, cls).__new__(cls, name, bases, attrs)
return new_cls
class MixinForm(object):
__metaclass__ = MixinFormMetaclass
def __init__(self, *args, **kwargs):
self.fields = deepcopy(self.declared_fields)
您现在可以从 MixinForm 派生表单字段集合,如下所示:
class SwallowFormFields(MixinForm):
airspeed_velocity = forms.IntegerField()
is_migratory = forms.BooleanField()
class MoreFormFields(MixinForm):
is_endangered = forms.BooleanField()
然后将它们添加到基类列表中,如下所示:
class EuropeanSwallowForm(forms.Form, SwallowFormFields, MoreFormFields):
pass
class AfricanSwallowForm(forms.ModelForm, SwallowFormFields):
class Meta:
model = AfricanSwallow
那么它有什么作用呢?
- 元类收集 MixinForm 中声明的所有字段
- 然后它添加自定义
__init__
构造函数,以确保__init__
MixinForm 的方法被神奇地调用。 (否则你必须显式调用它。)
-
MixinForm.__init__
复制字段属性中声明的字段
请注意,我既不是 Python 专家,也不是 django 开发人员,并且元类是危险的。因此,如果您遇到奇怪的行为,最好坚持使用上面更详细的方法:)
祝你好运!