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 #??
Is there a way to achieve this?
Note: i don't have a ModelForm
, so the Meta
class with exclude
doesn't work.
You can alter the fields in a subclass by overriding the init method:
class LoginFormWithoutNickname(LoginForm):
def __init__(self, *args, **kwargs):
super(LoginFormWithoutNickname, self).__init__(*args, **kwargs)
self.fields.pop('nickname')
Django 1.7 addressed this in commit b16dd1fe019 for ticket #8620. In Django 1.7, it becomes possible to do nickname = None
in the subclass as the OP suggests. From the documentation changes in the commit:
It's possible to opt-out from a Field
inherited from a parent class by shadowing it. While any non-Field
value works for this purpose, it's recommended to use None
to make it explicit that a field is being nullified.
I found that, please comment if interested.
(in Django 1.7.4)
extending forms, with following code:
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 set field_1 as None, (the column in db is updated as Null)
MyForm_Extended_2 ignore the field (ignore the column in db during the save)
So, for my purpose, I use the second method.
I didn't like the fact (or so I understood) that the exclusion of a field in the second class using "class Meta:" still results in the unused field being in the db.
Perhaps the simplest way is to define an abstract class that has the fields shared by both classes. Then the two original classes above become subclasses of this new class. So the example given at the start of this thread might look the following. It's a bit more code, but this way you extend a subclass rather than do an (incomplete) exclusion from a super class.
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