0
votes

I created a registration form and two custom user types; students and parents. The registration works perfect for both users. The problem is when I go to django admin and view my users, the password for students is in a hashed algorithim, while for parent users the password field says "Invalid password format or unknown hashing algorithm". I'm unsure where the problem stems from, but assume it is from my parent form inheriting the register form. Any help will be appreciated, thanks!

forms.py

class ParentSignUpForm(RegisterForm):
    first_name = forms.CharField(widget=forms.TextInput(attrs={'class' : 'form-control', 'placeholder' : 'Parent first name', 'id' : 'parent-first', 'required' : 'true'}))
    last_name = forms.CharField(widget=forms.TextInput(attrs={'class' : 'form-control', 'placeholder' : 'Parent last name', 'id' : 'parent-last', 'required' : 'true'}))
    child_first_name = forms.CharField(widget=forms.TextInput(attrs={'class' : 'form-control', 'placeholder' : "Child's first name", 'id' : 'child-first', 'required' : 'true'}))

    def clean_password2(self):
        # Check that the two password entries match
        password = self.cleaned_data.get("password")
        password2 = self.cleaned_data.get("password2")
        if password and password2 and password != password2:
            raise forms.ValidationError("Passwords don't match")
        return password2

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

    class Meta:
        # what model you're using
        model = User

        # what fields from that model you want
        fields = ['email', 'password', 'password2']

views.py

def parent_sign_up(request):
    if request.method == 'POST':
        form = ParentSignUpForm(request.POST)

        if form.is_valid():
            user = form.save()
            return redirect('home')

    else:
        form = ParentSignUpForm()

    form = ParentSignUpForm()

    context = {'form' : form}
    return render(request, 'accounts/parent_sign_up.html', context)
2
Can you reduce that code to a minimal reproducible example that reproduces your problem. We don't need to see all your fields, just make a very simple toy model.PM 2Ring
I shortened it.user9948622
yeah, nah. Unfortunately making a reproducible example is different from shortening the code. Your problem is even more obscured now. Fortunately I had a copy of what you originally posted, although still no answers for you.lsh
@lsh FWIW, the site keeps the full edit history of questions and answers, just click on the edited x mins ago link.PM 2Ring

2 Answers

1
votes

set_password is a method so I'd suggest to do the following:

Replace:

user.set_password = self.cleaned_data["password"]

with

user.set_password(self.cleaned_data["password"])
0
votes

I can't say for certain, but your inherited forms are duplicating their parent's methods.

For example, you have RegisterForm.save being duplicated in StudentSignUpForm and ParentSignUpForm.

You also have the Meta being overridden with different data in the children. Between all this duplication and Django magic, I would simplify to something resembling the below and go from there.

Note: I haven't tested the below, it just removes some of the duplication. Hopefully it's easier to debug now.

class RegisterForm(forms.ModelForm):
    email = forms.EmailField(widget=forms.EmailInput(attrs={'class' : 'form-control', 'placeholder' : 'Email', 'id' : 'email', 'required' : 'true'}))
    first_name = forms.CharField(widget=forms.TextInput(attrs={'class' : 'form-control', 'placeholder' : 'First name', 'id' : 'first-name', 'required' : 'true'}))
    last_name = forms.CharField(widget=forms.TextInput(attrs={'class' : 'form-control', 'placeholder' : 'Last name', 'id' : 'last-name', 'required' : 'true'}))
    password = forms.CharField(widget=forms.PasswordInput(attrs={'class' : 'form-control', 'placeholder' : 'Password', 'id' : 'password', 'required' : 'true'}))
    password2 = forms.CharField(widget=forms.PasswordInput(attrs={'class' : 'form-control', 'placeholder' : 'Confirm password', 'id' : 'password2', 'required' : 'true'}))

    class Meta:
        model = User
        # what fields from that model you want
        fields = ('first_name', 'last_name', 'email', 'password', 'password2')

    def clean_email(self):
        email = self.cleaned_data.get('email')
        qs = User.objects.filter(email=email)
        if qs.exists():
            raise forms.ValidationError("Email is taken")
        return email

    def clean_password2(self):
        # Check that the two password entries match
        password = self.cleaned_data.get("password")
        password2 = self.cleaned_data.get("password2")
        if password and password2 and password != password2:
            raise forms.ValidationError("Passwords don't match")
        return password2

    def save(self, commit=True):
        # Save the provided password in hashed format
        user = super(RegisterForm, self).save(commit=False)
        user.first_name = self.cleaned_data["first_name"]
        user.last_name = self.cleaned_data["last_name"]
        user.set_password = self.cleaned_data["password"]
        #user.active = False send confirmation email
        if commit:
            user.save()
        return user

class StudentSignUpForm(RegisterForm):

    def save(self, commit=True):
        user = super(StudentSignUpForm, self).save(commit=False)
        user.student = True
        if commit:
            user.save()
        return user

class ParentSignUpForm(RegisterForm):
    first_name = forms.CharField(widget=forms.TextInput(attrs={'class' : 'form-control', 'placeholder' : 'Parent first name', 'id' : 'parent-first', 'required' : 'true'}))
    last_name = forms.CharField(widget=forms.TextInput(attrs={'class' : 'form-control', 'placeholder' : 'Parent last name', 'id' : 'parent-last', 'required' : 'true'}))
    child_first_name = forms.CharField(widget=forms.TextInput(attrs={'class' : 'form-control', 'placeholder' : "Child's first name", 'id' : 'child-first', 'required' : 'true'}))

    def save(self, commit=True):
        user = super(ParentSignUpForm, self).save(commit=False)
        user.child_first_name = self.cleaned_data["child_first_name"]
        user.parent = True
        if commit:
            user.save()
        return user