Search code examples
djangoforeign-keysdjango-rest-frameworkextending

django rest framework - extending the auth.user without changing existing code


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


Solution

  • 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