Reputation: 1061
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
Upvotes: 6
Views: 2717
Reputation: 5867
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.
Upvotes: 3
Reputation: 3941
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
Upvotes: 0
Reputation: 9245
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 passingrequest
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.
Upvotes: 1