Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extending UserCreationForm: password not saved

Tags:

python

django

I've successfully created and extended the UserCreationForm to get email, first_name & last_name. It works fine in inserting all values. But I think the password field is not being saved. I'm using the built-in auth object to authenticate the user to login to my site. When the use register in the site and tries to login the password doesn't matches and the user cannot login. When I change the password from admin, I can login successfully. So, can anyone help me? This is how I've extended UserCreationForm:

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


class RegistrationForm(UserCreationForm):
    email = forms.EmailField(required=True)
    first_name = forms.TextInput()
    last_name = forms.TextInput()

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

    def save(self, commit=True):
        user = super(UserCreationForm, self).save(commit=False)
        user.email = self.cleaned_data['email']
        user.first_name = self.cleaned_data['first_name']
        user.last_name = self.cleaned_data['last_name']

        if commit:
            user.save()

        return user

How I change my password usgin admin? Now, I click the form link and I change the password.

like image 809
Anish Silwal Avatar asked Jan 18 '16 07:01

Anish Silwal


1 Answers

The problem

def save(self, commit=True):
    user = super(UserCreationForm, self).save(commit=False)
                 ^
                 |___ super of UserCreationForm is ModelForm!

Your code is calling super of UserCreationForm and not the super of your own form RegistrationForm. (The super of UserCreationForm being ModelForm has no idea how to handle user registration like password saving)

The result is that user.set_password() wasn't being called anywhere

However, I'd say no need to call user.set_password again since your super already does.

UserCreationForm.save() is defined as follows:

def save(self, commit=True):
    user = super(UserCreationForm, self).save(commit=False)
    user.set_password(self.cleaned_data["password1"])
    if commit:
        user.save()
    return user

Source code on github

Solution

You should have something like this

def save(self, commit=True):
    # Call save of the super of your own class,
    # which is UserCreationForm.save() which calls user.set_password()
    user = super(RegistrationForm, self).save(commit=False) 

    # Add the things your super doesn't do for you
    user.email = self.cleaned_data['email']
    user.first_name = self.cleaned_data['first_name']
    user.last_name = self.cleaned_data['last_name']

    if commit:
        user.save()

    return user
like image 178
bakkal Avatar answered Oct 20 '22 10:10

bakkal