Django UserCreationForm with one password

Viewed 3610

I'm wondering if I could make UseCreationForm without password confirmation (only password1). Code I'm working with:

#forms.py
class UserRegistrationForm(UserCreationForm):
    email = forms.EmailField(max_length=200, help_text='Required')

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

#views.py
class HomeView(View):
    template_name = 'home.html'

    def get(self, request):
        queryset = Profile.objects.filter(verified=True)
        form = UserRegistrationForm()
        context = {
            'object_list': queryset,
            'form':form,
            'num_of_users': User.objects.all().count()
        }
        return render(request, self.template_name, context)

The problem is, that when I make forms.py as that:

class UserRegistrationForm(UserCreationForm):
    email = forms.EmailField(max_length=200, help_text='Required')

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

Form has also field password2. Any solution of that?

3 Answers

The reason your form has two password fields is because your form inherits two fileds from the parent class, UserCreationForm:

## Based on actual Django source code
class UserCreationForm(forms.ModelForm):
    password1 = forms.CharField(...)
    password2 = forms.CharField(...)

If you want to remove one of the fields, all you have to do is set it to None in your child class.

However, In Django 2.1, the default UserCreationForm uses password2 to validate the password against the sitewide validators defined in settings.AUTH_PASSWORD_VALIDATORS (source: link)

An easy way to retain password validation, while also removing password2, is to set password2 = None and define clean_password1:

from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import password_validation

class UserRegistrationForm(UserCreationForm):
    email = forms.EmailField(max_length=200, help_text='Required')
    password2 = None

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

    def clean_password1(self):
        password1 = self.cleaned_data.get('password1')
        try:
            password_validation.validate_password(password1, self.instance)
        except forms.ValidationError as error:

            # Method inherited from BaseForm
            self.add_error('password1', error)
        return password1

You can override "password2" with None value.

class UserRegistrationForm(UserCreationForm):
    password2 = None

    class Meta:
        ...
Related