Django modelform how to add a confirm password field?
Asked Answered
K

5

27

Here I need to add an extra confirmation password in my form.I used Django's modelform. I also need to validate both passwords. It must raise a validation error if password1 != password2.

Here is my forms.py:

class UserForm(forms.ModelForm):
    password=forms.CharField(widget=forms.PasswordInput())

    class Meta:
        model=User
        fields=('username','email','password')

class UserProfileForm(forms.ModelForm):
    YESNO_CHOICES = (('male', 'male'), ('female', 'female'))
    sex = forms.TypedChoiceField(choices=YESNO_CHOICES, widget=forms.RadioSelect)
    FAVORITE_COLORS_CHOICES=(('red','red'),('blue','blue'))
    favorite_colors = forms.MultipleChoiceField(required=False,widget=forms.CheckboxSelectMultiple, choices=FAVORITE_COLORS_CHOICES)
    dob = forms.DateField(widget=forms.DateInput(format = '%d/%m/%Y'), 
                                 input_formats=('%d/%m/%Y',))

    class Meta:

        model=UserProfile
        fields=('phone','picture','sex','favorite_colors','dob')

And here is my registration function:

def register(request):
    registered = False
    if request.method == 'POST':
        user_form = UserForm(data=request.POST)
        profile_form = UserProfileForm(data=request.POST)



        if user_form.is_valid() and profile_form.is_valid():
            user = user_form.save(commit=False)
            user.set_password(user.password)
            user.save()
            profile = profile_form.save(commit=False)
            profile.user = user
            if 'picture' in request.FILES:
                profile.picture = request.FILES['picture']
            profile.save()
            registered = True
        else:
            print user_form.errors, profile_form.errors
    else:
        user_form = UserForm()
        profile_form = UserProfileForm()

    return render(request,
            'mysite/register.html',
            {'user_form': user_form, 'profile_form': profile_form, 'registered': registered} )
Kablesh answered 5/1, 2016 at 10:48 Comment(0)
O
38

Use clean like

class UserForm(forms.ModelForm):
    password=forms.CharField(widget=forms.PasswordInput())
    confirm_password=forms.CharField(widget=forms.PasswordInput())
    class Meta:
        model=User
        fields=('username','email','password')

    def clean(self):
        cleaned_data = super(UserForm, self).clean()
        password = cleaned_data.get("password")
        confirm_password = cleaned_data.get("confirm_password")

        if password != confirm_password:
            raise forms.ValidationError(
                "password and confirm_password does not match"
            )
Ot answered 17/1, 2016 at 11:38 Comment(2)
I keep having AttributeError 'str' object has no attribute 'get'Minsk
If you have multiple rules, this will stop at the first error and won't show the other errors, other solution is better IMOGiff
K
15
def clean(self):
    cleaned_data = super(UserAccountForm, self).clean()
    password = cleaned_data.get("password")
    confirm_password = cleaned_data.get("confirm_password")

    if password != confirm_password:
        self.add_error('confirm_password', "Password does not match")

    return cleaned_data
Kempis answered 15/9, 2017 at 23:15 Comment(1)
Thanks! add_error()is much better than raise forms.ValidationError so you can display all errors instead of only showing the first errorGiff
A
2

Try this for forms.py:

class UserForm(forms.Form):
    password = forms.CharField(widget=forms.PasswordInput())
    password_confirm = forms.CharField(widget=forms.PasswordInput())

    class Meta:
        model = User
        fields=('username','email','password')

And this in views.py:

if user_form.is_valid() and profile_form.is_valid() and user_form.cleaned_data['password'] == user_form.cleaned_data['password_confirm']:
    ...
elif user_form.data['password'] != user_form.data['password_confirm']:
    user_form.add_error('password_confirm', 'The passwords do not match')
Awake answered 16/1, 2016 at 18:51 Comment(0)
A
1

You can have a look at how Django does it for UserCreationForm.

    def clean_password2(self):
        password1 = self.cleaned_data.get("password1")
        password2 = self.cleaned_data.get("password2")
        if password1 and password2 and password1 != password2:
            raise ValidationError(
                self.error_messages['password_mismatch'],
                code='password_mismatch',
            )
        return password2

Here password2 refers to the confirm_password field, under the assumption that it appears after the password field. Trying to use the same implementation for clean_password may lead to an error that the confirm_password data wasn't found.

This has the advantage that you're raising the error for a particular Field, instead of the whole form, which you can then render appropriately in your template.

However, if you're trying to validate data across multiple fields, the documentation advises overriding the clean() method, as answered by Savai.

The source code is available here.

Alexandriaalexandrian answered 11/7, 2020 at 3:58 Comment(0)
T
0

Confirm password is already available in UserCreationForm

class UserRegistrationForm(UserCreationForm):
    email = forms.EmailField(required=True)

    class Meta:
        model = User
        fields = ("username", "email", "password1", "password2")

This will automatically verify password1==password2 when form.is_valid() is called.

Here I am only taking email as a separate form arguments for further clean up and validation

Torrey answered 7/1, 2023 at 17:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.