Barburka
Barburka

Reputation: 465

Django UserCreationForm with one password

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?

Upvotes: 7

Views: 4292

Answers (3)

Milad Hatami
Milad Hatami

Reputation: 1650

You can override "password2" with None value.

class UserRegistrationForm(UserCreationForm):
    password2 = None

    class Meta:
        ...

Upvotes: 0

touch my body
touch my body

Reputation: 1733

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

Upvotes: 6

wencakisa
wencakisa

Reputation: 5968

You can override the __init__() method of your form and remove the field you want:

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

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

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        del self.fields['password2']

Important: Anyway, it is not a common practice to have only one field for password, because user can mistype it. And security level decreases a lot.

Upvotes: 8

Related Questions