Django: удалить поле из подкласса Form
class LoginForm(forms.Form):
nickname = forms.CharField(max_length=100)
username = forms.CharField(max_length=100)
password = forms.CharField(widget=forms.PasswordInput)
class LoginFormWithoutNickname(LoginForm):
# i don't want the field nickname here
nickname = None #??
Есть ли способ достичь этого?
Примечание: у меня нет ModelForm
, поэтому класс Meta
с exclude
не работает.
Ответы
Ответ 1
Вы можете изменить поля в подклассе, переопределив метод init:
class LoginFormWithoutNickname(LoginForm):
def __init__(self, *args, **kwargs):
super(LoginFormWithoutNickname, self).__init__(*args, **kwargs)
self.fields.pop('nickname')
Ответ 2
Django 1.7 обратился к этому в commit b16dd1fe019 для билета # 8620. В Django 1.7 становится возможным сделать nickname = None
в подклассе, как предлагает OP. Из изменений документации в фиксации:
Можно отказаться от Field
, унаследованного от родительского класса, затеняя его. Хотя для этой цели используется любое значение Field
, рекомендуется использовать None
, чтобы сделать его явным, что поле сбрасывается.
Ответ 3
Я нашел это, пожалуйста, прокомментируйте, если вы заинтересованы.
(в Django 1.7.4)
расширяющие формы, со следующим кодом:
class MyForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
for key, field in self.fields.iteritems():
self.fields[key].required = False
class Meta:
model = MyModel
exclude = []
field_1 = forms.CharField(label="field_1_label")
field_2 = forms.CharField(label="field_2_label", widget=forms.Textarea(attrs={'class': 'width100 h4em'}),)
field_3 = forms.CharField(label="field_3_label", widget=forms.TextInput(attrs={'class': 'width100'}),)
field_4 = forms.ModelChoiceField(label='field_4_label', queryset=AnotherModel.objects.all().order_by("order") )
class MyForm_Extended_1(MyForm):
field_1 = None
class MyForm_Extended_2(MyForm):
class Meta:
model = MyModel
exclude =[
'field_1',
]
MyForm_Extended_1 установить field_1 как None (столбец в db обновлен как Null)
MyForm_Extended_2 игнорировать поле (игнорировать столбец в db во время сохранения)
Итак, для моей цели я использую второй метод.
Ответ 4
Мне не понравился факт (или так я понял), что исключение поля во втором классе с использованием "класса Meta:" по-прежнему приводит к тому, что неиспользуемое поле находится в db.
Возможно, самым простым способом является определение абстрактного класса с полями, разделяемыми обоими классами. Тогда два оригинальных класса выше становятся подклассами этого нового класса. Таким образом, пример, приведенный в начале этого потока, может выглядеть следующим образом. Это немного больше кода, но таким образом вы расширяете подкласс, а не исключаете (неполное) исключение из суперкласса.
class LoginForm_Common(forms.Form):
username = forms.CharField(max_length=100)
password = forms.CharField(widget=forms.PasswordInput)
class Meta:
abstract = True
class LoginForm(LoginForm_Common):
nickname = forms.CharField(max_length=100)
class LoginFormWithoutNickname(LoginForm_Common):
pass