0

I am working in django rest framework and building a RESTful api to access from android app.

I want to extend the user model and add a phone number field - but I have models with foreign keys to the user models and also Token based authentication.

for example:

class Ride(models.Model):
    driver = models.ForeignKey('auth.User')
    destination=models.ForeignKey(Destination)

And obviously I have default users table and as I said - Token authentication - (generate token on register, then client login - sends username:password and gets token login).

My question is:

How can I add this field to the user with minimum changing of code/models/views, and in the best way possible? I read a lot of answers about this topic, just want to use the best option.

------------ EDIT --------------

After adding the UserProfile I am having trouble creating a user, here is the code:

serializers.py:

class UserSerializer(serializers.ModelSerializer):

    class Meta:
        model = User
        fields = ('id', 'username', 'first_name', 'last_name', 'password', )
        extra_kwargs = {'password': {'write_only': True}}

    def create(self, validated_data):
        user = User(
            first_name=validated_data['first_name'],
            username=validated_data['username'],
            last_name=validated_data['last_name']
        )

        user.set_password(validated_data['password'])
        user.save()
        user.UserProfile.phone_number = self.initial_data["phone_number"]
        return user

Models.py

class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    phone_number = models.CharField(max_length=15)

@receiver(post_save, sender=User)
def handle_user_save(sender, instance=None, created=False, **kwargs):
    if created:
        UserProfile.objects.create(user=instance)
        Token.objects.create(user=instance)

The user.save() calls the handle_user_save method - and then I create the UserProfile.

The thing is - after I create it - I can't update its field from the user. the problem is in this line:

user.UserProfile.phone_number = self.initial_data["phone_number"]

It throws exception - "User doesn't have field UserProfile".

how should I do this?

thanks

2
  • I suggest to use onetoone field. Commented Oct 27, 2015 at 6:59
  • thanks for your answer. what will I have to change if I use OneToOne field? can you point me to an example? Commented Oct 27, 2015 at 12:59

1 Answer 1

5

The OneToOne field mentioned most likely refers to the Django suggested way for Extending the Existing User Model.

The suggestion is that you create a new model, UserProfile for example, and add any of the new fields you need there. The UserProfile will link to the User model utilizing a OneToOne field.

from django.contrib.auth.models import User

class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    new_field = models.CharField(max_length=100)

All foreign key reference from other models should still point to Django's user model. When you need the new field you've added, you can just pull the profile from the user:

user = Users.objects.get(username='example')
print user.userprofile.new_field
Sign up to request clarification or add additional context in comments.

4 Comments

thanks for your answer. so about changes I'll have to make if I use OneToOne field - I'll obviously have to change the foreign key to point to UserProfile and not auth.user. also in the UserViewSet, right? one more question I have is - if I do self.request.user, will I get the auth.user or UserProfile? thanks again!
@OfekAgmon - I've corrected my last bit, it was slightly wrong and might have led you astray. Foreign keys should still point directly at the user model the way you are currently doing it. You can just access the UserProfile as a field on the User object, and then from there access any of the new fields you've added to the UserProfile.
thanks again. I an having trouble registering the user right now - editing my question with the code.
@OfekAgmon - The issue might be with how you are referencing the UserProfile. The proper way that a default backwards-relationship is named is all lowercase. See Docs here. I've updated my answer to reflect this.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.