Reputation: 469
So I know that Django has a built in system with the User, and it contains things like Username, e-mail, password, and first and last name. I want to know how I can utilise this in my site.
So I have a first_name and last_name field in the models.py file, and they are CharFields. I want to know how to connect them to the already existing UserForm that comes with Django.
I have tried a few things already, such as doing this with the models.py file.
class UserProfileInfo(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
first_name = models.OneToOneField(User, on_delete=models.CASCADE)
Here is some code for the form.py file.
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput())
class Meta():
model = User
fields = ('username','email','password','first_name')
As you can see from the form, I added the first_name attribute, and in the models.py file, I have the first_name connected with the forms.py one. I am now getting this error.
HINT: Add or change a related_name argument to the definition for 'UserProfileInfo.user' or 'UserProfileInfo.first_name'.
So I added a related name field to the model, as shown here
first_name = models.OneToOneField(User, on_delete=models.CASCADE,related_name='first_name')
But, wouldn't you know it, I got yet another error:
ValueError: Cannot assign "''": "User.first_name" must be a "UserProfileInfo" instance.
I don't really know what is going on here.
So I expected to get no errors, just like the user field. Instead I got this error. Any help would be greatly appreciated :)
Upvotes: 0
Views: 319
Reputation: 1261
Your code is setting a OneToOne
to the User
model for both the user
and first_name
fields. So this means the related field will be User.id
for both.
To specify that you want UserProfileInfo.first_name
to map to User.first_name
you will need to set to_field=first_name
class UserProfileInfo(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
first_name = models.OneToOneField(User, on_delete=models.CASCADE, to_field='first_name', related_name='user_profile_first_name')
However, this will still cause an issue as you can only set a OneToOne
relationship to a unique field. As User.first_name
is not unique, you cannot set a OneToOne
relationship to it.
If both the OneToOne
relationships are referencing the same object, one of the relationships is redundant as you can access the fields on that object through the other relationship. It would be better to have a method on UserProfileInfo
that gets the first name through the user
field.
class UserProfileInfo(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
def get_first_name(self):
return user.first_name
You will also need to set signals to create/update UserProfileInfo
when User
is created/updated. Have a look at this article.
There are also other ways to extend the User
model in Django. Have a look at this article or this answer for suggestions.
But if you're not adding any extra fields to the User
model, it may be better just to use it directly.
Upvotes: 1