简体   繁体   中英

Django form not saving password when creating user

I have made a custom form for my django app which allows users to register themselves for the website.

This is the form for my django app:

class TeacherRegistrationForm(UserCreationForm):
    email = forms.EmailField(required = True)
    school = forms.CharField(required = True)
    subject = forms.CharField(required = True)
    head_of_subject = forms.BooleanField(required = False)
    identification_code = forms.CharField(required = True)

    def __init__(self, *args, **kwargs):
        super(TeacherRegistrationForm, self).__init__(*args, **kwargs)
        self.fields['username'].help_text = ''
        self.fields['password2'].help_text = ''


    class Meta:
        model = User

        fields = (
            'username',
            'first_name',
            'last_name',
            'email',
            'school',
            'identification_code',
            'subject',
            'head_of_subject',
            'password1',
            'password2'            
        )

    def save(self, request):
        form = TeacherRegistrationForm(request.POST)
        user = User.objects.create(first_name=self.cleaned_data['first_name'],
                            last_name=self.cleaned_data['last_name'],
                            email=self.cleaned_data['email'],
                            username=self.cleaned_data['username'],
                            password=self.cleaned_data['password1']
                            )

        teacher_profile = TeacherProfile.objects.create(user=user,
                                                        school=self.cleaned_data['school'],
                                                        subject=self.cleaned_data['subject'],
                                                        head_of_subject=self.cleaned_data['head_of_subject'],
                                                        )


        return user, teacher_profile

This is the relevant part of the view:

if request.method == 'POST':

        form = TeacherRegistrationForm(request.POST)

        entered_school_name = form['school'].value()
        entered_school_id = form['identification_code'].value()

        actual_school_id = SchoolProfile.objects.get(school_name__exact = entered_school_name).identification_code

        if form.is_valid()and (entered_school_id == actual_school_id):

            user, teacher_profile = form.save(request)

            return render(request, 'accounts/home.html')
        else:
            args = {'form': form}
            return render(request, 'accounts/reg_form.html', args)

When I press submit, the user is created, however no password is set for the user

There's no need to touch any of the fields that are part of User, and in fact you shouldn't do that but instead let the UserCreationForm handle it because there's some special handling for password in there.

Do it like so, in your form class save method:

def save(self):
    user = super(TeacherRegistrationForm, self).save()
    teacher_profile = TeacherProfile(
        user=user,
        school=self.cleaned_data['school'],
        subject=self.cleaned_data['subject'],                   
        head_of_subject=self.cleaned_data['head_of_subject']
    )
    teacher_profile.save()
    return user, teacher_profile

This will result in the TeacherRegistrationForm, which is a subclass of UserCreationForm, which is in turn a subclass of ModelForm.. will do what ModelForm is supposed to do, which is to save itself to the database (user table) when you call its save method. So that's all done for you. Then you just have to handle the extra fields you added to the form for the other model.

And notice I used the model save() method instead of using create() , which in this case accomplishes the same thing.. but you could later on modify the form code to allow the same form to edit an existing model not just create a new one. Let me know if you would like me to explain that too.

Try editing your form like this,

def save(self): 
    user = User.objects.create_user(username=self.cleaned_data['username'], password=self.cleaned_data['password1']) 
    user.first_name = self.cleaned_data['first_name']
    user.last_name = self.cleaned_data['last_name']
    user.email = self.cleaned_data['email']
    user.save()
    teacher_profile = TeacherProfile.objects.create(user=user, school=self.cleaned_data['school'], subject=self.cleaned_data['subject'], head_of_subject=self.cleaned_data['head_of_subject'] ) 
    return user, teacher_profile

Use User.objects.create_user() rather than objects.create .

I don't see the point of passing request into the save method. You can remove that part. save method is called when form.save() is executed. Also, saving form again in the form save method is actually unnecessary.

No need of save user in custom way, you inherited UserCreationForm that will return user instance after set password and with validation So you will get direct user instance in super call.

def save(self, request):       
   user = super(TeacherRegistrationForm, self).save()
   teacher_profile = TeacherProfile.objects.create(user=user,                                         
                      school=self.cleaned_data['school'], 
                      subject=self.cleaned_data['subject'],                                                            
                      head_of_subject=self.cleaned_data['head_of_subject'],
                    )
   return user, teacher_profile

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM