Benjamin Smith Max
Benjamin Smith Max

Reputation: 2748

Custom form using User model

I have a form to register users using the User model.

forms:

class UserForm(forms.ModelForm):
    class Meta:
        model = User
        fields = ['first_name', 'last_name', 'username', 'email', 'password']

template:

{% block content %}
    <p>Register</p>
    {{ user_form.as_p }}
{% endblock %}

views.py:

def register_view(request):
    if request.method == "POST":
        user_form = UserForm(request.POST)
        if user_form.is_valid:
            user = user_form.save()
            return  HttpResponseRedirect('/account/registered/')
    else:
        user_form = UserForm()
    return render(request, 'register_view.html', {
        'user_form': user_form
    })

But I need to add additional features in the form:

  1. Display email field twice and validate both email fields on submission.
  2. Min length of password to be 8 characters.

I tried settings the email field twice inside the list of fields:

fields = ['first_name', 'last_name', 'username', 'email', 'password']

But its displaying just one email field.

How can I customize the form using the ModelForm to my needs?

Updated

Updated my form using the answer but now I am getting the error:

KeyError at /account/register/

'confirm_email'

Updated form:

class UserForm(forms.ModelForm):
    confirm_email = forms.EmailField(label="Confirm email")

    def clean(self):
        email = self.cleaned_data['email']
        confirm_email = self.cleaned_data['confirm_email']
        password = self.cleaned_data['password']

        if email != confirm_email:
            raise ValidationError({'confirm_email': "Both email doesn't match."})

        if len(password) < 8:
            raise ValidationError({'password': "Password should be of minimum 8 characters."})

        return super(UserForm, self).clean()

    class Meta:
        model = User
        fields = ['first_name', 'last_name', 'username', 'email', 'confirm_email', 'password']

Upvotes: 1

Views: 269

Answers (1)

GwynBleidD
GwynBleidD

Reputation: 20539

You should create second field email inside your form and validate if both emails are identical in clean method, like this:

class UserForm(forms.ModelForm):
    confirm_email = forms.EmailField(label="Confirm email")

    def clean(self):
        email = self.cleaned_data['email']
        confirm_email = self.cleanded_data['confirm_email']

        if email != confirm_email:
            raise ValidationError({'confirm_email': "provided email doesn't match with above one"})

        return super(UserForm, self).clean()

    class Meta:
        model = User
        fields = ['first_name', 'last_name', 'username', 'email', 'password']

Same thing you should do with your password. Remember to save actual password using set_password method on your user, don't store raw password in database.

Upvotes: 1

Related Questions