Creating Custom User Profiles in Django

If you're using Django to build a complex system, you have probably encountered situations where you needed multiple types of profiles to handle different system users, such as buyers and sellers, customers and suppliers, or regular users and VIP users.

The default Django User model won't be sufficient when you need to extend it with additional fields. In such cases, you need to create custom user profiles.

Extending the User Model

First, we'll use the AbstractUser class, which provides a user profile without the unnecessary fields that you wouldn't need when extending the User model. Here's how to do it in a models.py file of an installed app in your project:


from django.db import models
from django.contrib.auth.models import AbstractUser

class CustomUser(AbstractUser):
    is_supplier = models.BooleanField(default=False)
    is_customer = models.BooleanField(default=False)

class Supplier(models.Model):
    user = models.OneToOneField(CustomUser, on_delete=models.CASCADE)
    # Add supplier-specific fields here

class Customer(models.Model):
    user = models.OneToOneField(CustomUser, on_delete=models.CASCADE)
    # Add customer-specific fields here
        

Here, CustomUser replaces the main Django User model, and we add boolean fields to define the user types (e.g., a user might be both a supplier and a customer). Then, we define the specific user types as models connected to our main CustomUser. You can add as many profiles as needed with their respective fields.

Creating Views and Serializers

Next, we create the views. This depends on how you're building the system. If you're using Django REST Framework (like I am), you need to serialize the models of profiles and CustomUser. Ensure that when creating a supplier, the is_supplier field is set to True, and do the same for other user types.


from rest_framework import serializers
from .models import CustomUser, Supplier, Customer

class CustomUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = CustomUser
        fields = ('username', 'password', 'email', 'is_supplier', 'is_customer')
        extra_kwargs = {'password': {'write_only': True}}

    def create(self, validated_data):
        user = CustomUser.objects.create_user(**validated_data)
        return user

class SupplierSerializer(serializers.ModelSerializer):
    user = CustomUserSerializer()

    class Meta:
        model = Supplier
        fields = ('user',)

    def create(self, validated_data):
        user_data = validated_data.pop('user')
        user = CustomUser.objects.create_user(**user_data, is_supplier=True)
        supplier = Supplier.objects.create(user=user, **validated_data)
        return supplier

class CustomerSerializer(serializers.ModelSerializer):
    user = CustomUserSerializer()

    class Meta:
        model = Customer
        fields = ('user',)

    def create(self, validated_data):
        user_data = validated_data.pop('user')
        user = CustomUser.objects.create_user(**user_data, is_customer=True)
        customer = Customer.objects.create(user=user, **validated_data)
        return customer
        

Creating Views


from rest_framework import generics
from .models import Supplier, Customer
from .serializers import SupplierSerializer, CustomerSerializer
from rest_framework.permissions import AllowAny

class SupplierCreate(generics.CreateAPIView):
    queryset = Supplier.objects.all()
    serializer_class = SupplierSerializer
    permission_classes = [AllowAny]

class CustomerCreate(generics.CreateAPIView):
    queryset = Customer.objects.all()
    serializer_class = CustomerSerializer
    permission_classes = [AllowAny]
        

Finally, go to your settings.py file and add:

AUTH_USER_MODEL = 'app.CustomUser'

Then, register the URLs for these views.

Now you can create custom profiles for users, grant each user type permissions, and create different views based on user types.