[Django]-Django REST Framework Creating custom user


So apparently I don’t have enough reputation to post a comment under an answer. But to elaborate on what Kevin Stone described, if you model is something like the following:

class AppUser(models.Model):
    user = models.OneToOneField(User)
    ban_status = models.BooleanField(default=False)

You can do something like this to create both the custom user and django user:

class AppUserSerializer(serializers.ModelSerializer):
    username = serializers.CharField(source='user.username')
    email = serializers.CharField(source='user.email')
    password = serializers.CharField(source='user.password')
    ban_status = serializers.Field(source='ban_status')

    class Meta:
        model = AppUser
        fields = ('id', 'username', 'email', 'password', 'ban_status')

    def restore_object(self, attrs, instance=None):
        Given a dictionary of deserialized field values, either update
        an existing model instance, or create a new model instance.
        if instance is not None:
            instance.user.email = attrs.get('user.email', instance.user.email)
            instance.ban_status = attrs.get('ban_status', instance.ban_status)
            instance.user.password = attrs.get('user.password', instance.user.password)
            return instance

        user = User.objects.create_user(username=attrs.get('user.username'), email= attrs.get('user.email'), password=attrs.get('user.password'))
        return AppUser(user=user)


Okay, a couple of things. You want to create a OneToOneField for your user model extension.

class MyUser(models.Model):
    user = models.OneToOneField(User)
    city = models.CharField(max_length=50, blank=True, default='')

Now, the power of Django Rest Framework, is you can build your serializer, to take data from both of these models when serializing.

class UserSerializer(serializers.ModelSerializer):
    city = serializers.CharField(source='myuser.city')
    class Meta:
        model = User
        fields = ('id', 'username', 'password', 'first_name', 'last_name', 'email', 'city')

Finally, where you’re creating the user, since you’re using custom fields, you need to implement your own restore_object() that builds both models from the input data.

Also, creating Users in Django is a bit different, you need to call create_user() and supply a password that is hashed, so its not as simple as storing fields from a serializer.


It would be nice if this use case was easier to find in the docs. As @jamod pointed out, in DRF 3, you can find it here:

class UserSerializer(serializers.ModelSerializer):
    profile = ProfileSerializer()

    class Meta:
        model = User
        fields = ('username', 'email', 'profile')

    def create(self, validated_data):
        profile_data = validated_data.pop('profile')
        user = User.objects.create(**validated_data)
        Profile.objects.create(user=user, **profile_data)
        return user


When using Django Rest Framework you have to be careful. Any custom user model cannot utilize the built in token authentication. Until you can do that, I would suggest using a OneToOneField with user in your custom model. Your custom model will contain the extra fields you want to keep. One to One gives you access to the user from the custom user, and the custom user from the user.


If you’re using django 1.5 or greater then use custom user model instead, this way user model will have it’s own dedicated table and serializer will then pick up the fields correctly.


I prefer to use the django signals module, which sends signals to the app when something happens, and among other things will let you call a function of your own before/after other functions. My answer is similar to Stuart’s answer but keeps all of the code relevant to your new extension class in one place (if you want to delete the profile later or change its name you don’t have to look anywhere else).

The following code lays out your extended class model, in this case a user profile, then creates an empty instance when a user model is created, then saves the instance with new information (that you must add yourself) by saving the parent user instance i.e. – user.save()


from django.db.models.signals import post_save
from django.db import models
from django.contrib.auth.models import User

class Profile(models.Model): #This extends the user class to add profile information
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    #add your extra traits here: is_nice, is_shwifty, address, etc.
    is_nice = models.BooleanField(default=True, blank=True) 

# a user model was just created! This now creates your extended user (a profile):
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        # instance is the user model being saved.

# a user model was just saved! This now saves your extended user (a profile):
@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):

If you don’t have a ProfileSerializer: serializers.py

#use hyperlinkedmodelserializer for easy api browsing + clicking
class ProfileSerializer(serializers.HyperlinkedModelSerializer):
    user = UserSerializer() 
    class Meta:
        model = Profile
        fields = ('url', 'user', 'is_nice')

After you create your user and save your user, you’ll have an empty user.profile to add information to. For example, after running python manage.py shell

from backend.models import User, Profile
#create your user
#now update your user's profile
#that's one mean gravy boat

Leave a comment