Django form does not save password when creating user.
I created a custom form for my django app that allows users to register with the site.
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 click the Submit button, a user is created, however no password has been set for the user
source to share
You don't need to touch any fields that are part of User, and in fact you shouldn't, but instead let UserCreationForm handle it because there is special handling for the password there.
Do it like this, in the save method of the form class:
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 cause the TeacherRegistrationForm, which is a subclass of UserCreationForm, which in turn is 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 method conservation. So everything is done for you. Then you just need to handle the extra fields added to the form for another model.
And note that I used the save()
model method instead of using create()
, which does the same thing in this case. But later, you can modify the form code to allow the same form to edit the existing model, rather than just create a new one. Let me know if you would like me to explain this too.
source to share
Try changing the shape like
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()
instead objects.create
.
I don't see the transfer point request
in the save method. You can remove this part. save
the method is called when executed form.save()
. Also, saving the form again in the form save method isn't really necessary.
source to share
No need to save the user in your own way, you inherited UserCreationForm
, which will return the user instance after setting a password and validating. So you get a direct instance of the user in the 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
source to share