Reputation: 826
I am trying to extend Djangos authentication system and have a problem when trying to create the modelForm for it. As you can see below I have referenced the authentication backend via the suggested OneToOnefield however when I am creating the ModelForm if I try to reference the fields such as 'username', 'password' etc. it spits an error saying they are unknown fields. The form I am creating is a registration from. What am I doing wrong here? Cheers
Model -
class StudentModel(models.Model):
user = models.OneToOneField(User, unique=True)
birth_date = models.DateField()
contact_number = models.IntegerField()
referral = models.CharField(max_length=100, choices=referral_choices)
ModelForm -
from django import forms
from opus_login.models import StudentModel, EmployerModel
class StudentForm(forms.ModelForm):
class Meta:
model = StudentModel
fields = ['username', 'first_name']
Error -
django.core.exceptions.FieldError: Unknown field(s) (username, first_name) specified for StudentModel
Upvotes: 3
Views: 4492
Reputation: 51988
You can't directly access One2One fields like this. You need to first create a object of User
and add to One2One relation. You can try like this:
from django import forms
from opus_login.models import StudentModel, EmployerModel
class StudentForm(forms.ModelForm):
username = forms.CharField()
first_name = forms.CharField()
class Meta:
model = StudentModel
fields = ['__all__']
def save(self, **kwargs):
student = super().save(commit=False)
user = User.objects.create(username=self.cleaned_data['username'], first_name=self.cleaned_data['first_name'])
user.set_password(self.cleaned_data['password']) #if there is a password field
student.user = user
student.save(commit=True)
return student
Upvotes: 2
Reputation: 9110
A common solution when you need to extend the User
model with another model is use two ModelForm
s: one for User
and another for extending model (Student
in your case). In the first you access the needed fields of the User
model, in the second those of the Student
model.
class UserForm(forms.ModelForm):
password = forms.CharField(label='Password',widget=forms.PasswordInput)
password2 = forms.CharField(label='Repeat password',widget=forms.PasswordInput)
class Meta:
model = User
fields = ('username', 'first_name')
def clean_password2(self):
.......
return password2
class StudentForm(forms.ModelForm):
class Meta:
model = StudentModel
fields = ['birthdate', 'contact_number']
Then, in the view, you work with two forms instead of one. For example:
def register(request):
if request.method == 'POST':
user_form = UserForm(request.POST)
student_form = StudentForm(request.POST)
if user_form.is_valid() and student_form.is_valid():
user_form.save()
student_form.save()
And in your template you combine both forms in one:
<form action="." method="post">
{{ user_form.as_p }}
{{ student_form.as_p }}
{% csrf_token %}
<p><input type="submit" value="Register"></p>
</form>
Upvotes: 5