jeremy_lord
jeremy_lord

Reputation: 469

How can I utilise the built in first and last name features of the Django User Model?

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

Answers (1)

Mikey Lockwood
Mikey Lockwood

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

Related Questions