Вы можете использовать множественное наследование, также известное как 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
ОБНОВЛЕНИЕ:
Поскольку это не работает с метапрограммированием 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
ОБНОВЛЕНИЕ :
Конечно, вам не нужно вкладывать свои общие поляв класс - вы также можете просто определить их как глобальные переменные ...
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
ОБНОВЛЕНИЕ:
Хорошо, если вы действительно хотите СУХОЙ до максимумавам нужно использовать метаклассы .
. Вот как вы можете это сделать:
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, например:this:
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__
, чтобы убедиться, чтоЕсли магический метод MixinForm __init__
будет вызван.(В противном случае вам придется вызывать его явно.) MixinForm.__init__
копирует объявленные поля в атрибут field
Обратите внимание, что я не гуру Python и не разработчик djangoи что метаклассы опасны.Поэтому, если вы столкнетесь со странным поведением, лучше придерживайтесь более подробного подхода, описанного выше:)
Удачи!