Monday 17 January 2011

Django - Set field order on extending form

Let's assume you have two registration forms, one for regular user registration and the second for special user registration

The difference between those two would be that for regular user you'd only need, let's say, an email field and two password fields, so it would look like this:

class RegularUserForm(forms.Form):
    email = forms.EmailField(required=True, widget=forms.TextInput(attrs={'class': 'required'}), label="Email")
    password1 = forms.CharField(widget=forms.PasswordInput(attrs={'class': 'required'}), label="Password")
    password2 = forms.CharField(widget=forms.PasswordInput(attrs={'class': 'required'}), label="Confirm Password")

For the special user registration, the form might look like this:

class SpecialUserForm(forms.Form):
    username = forms.CharField(max_length=30, min_length=3, label="Username", widget=forms.TextInput(attrs={'class': 'required', 'id': 'username'}))
    email = forms.EmailField(required=True, widget=forms.TextInput(attrs={'class': 'required'}), label="Email")
    password1 = forms.CharField(widget=forms.PasswordInput(attrs={'class': 'required'}), label="Password")
    password2 = forms.CharField(widget=forms.PasswordInput(attrs={'class': 'required'}), label="Confirm Password")
    first_name = forms.CharField(label="First Name", required=False)
    middle_name = forms.CharField(label="Middle Name", required=False)
    last_name = forms.CharField(label="Last Name", required=False)
    institution = forms.CharField(label="Institution", required=False)

Now, this isn't very nice, is it? We added emai, password1 and password2 fields to the second form. This is not a good practice, so the solution is to make the SpecialUserForm extend the RegularUserForm. Then our form will look like this:

class SpecialUserForm(RegularUserForm):
    username = forms.CharField(max_length=30, min_length=3, label="Username", widget=forms.TextInput(attrs={'class': 'required', 'id': 'username'}))
    first_name = forms.CharField(label="First Name", required=False)
    middle_name = forms.CharField(label="Middle Name", required=False)
    last_name = forms.CharField(label="Last Name", required=False)
    institution = forms.CharField(label="Institution", required=False)

But we stumble on another problem. The form fields' order would now be: username, first_name, middle_name, last_name, institution, email, password1, password2. It's not very pretty, but luckily django allows us to take control over the fields' order.

For this, we will add to the SpecialUserForm an __init__ function where we will control the fields' order:

def __init__(self, *args, **kw):
    super(RegularUserForm, self).__init__(*args, **kw)
    self.fields.keyOrder = [
        'username',
        'email',
        'password1',
        'password2',
        'first_name',
        'last_name']

No comments:

Post a Comment