Django Rest Framework – creating users

First, I create a new application called users.

python startapp users

In the file, I create a custom user that inherits from the AbstractUser class. I’m adding a role checkbox so that the user will be either a principal or a contractor (client or contractor).

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

class ContractUser(AbstractUser):
    class RoleChoices(models.TextChoices):
        CLIENT = "client"
        CONTRACTOR = "contractor"

    role = models.CharField(

    def __str__(self):
        return self.username

The new user model should be registered in the project’s file, i.e.

AUTH_USER_MODEL = "users.ContractUser"

In the users application, I create a file containing the serializer of the new user model, i.e.

from django.contrib.auth.hashers import make_password
from rest_framework import serializers
from .models import ContractUser

class ContractUserSerializer(serializers.ModelSerializer):
    password = serializers.CharField(
        style={"input_type": "password"}

    class Meta:
        model = ContractUser
        fields = [

    def create(self, validated_data):
        validated_data["password"] = make_password(validated_data["password"])
        return super().create(validated_data)

The serializer includes a CharField to enter a password. This field contains the write_only parameter set to True to allow only writing and not reading of this field. The fields field of the Meta internal class contains a list of all available serializable fields. The create() method creates a password based on user input using the make_password() function.

In the file of the users application, I define an endpoint, i.e.

from rest_framework.routers import DefaultRouter
from .views import ContractUserCreateRetrieveViewSet

router = DefaultRouter()

router.register("", ContractUserCreateRetrieveViewSet, basename="user")

urlpatterns = router.urls

I attach the endpoint for the users application to the main file of the project:

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path("api/user/", include("users.urls")),

The /api/user/ endpoint will allow you to create a user and view data for a given user. To do this, I create a ContractUserCreateRetrieveViewSet() class in the file. To limit the number of available methods, I do not use the ModelViewSet class, but inherit from the GenericViewSet class and the appropriate Mixin classes.

from django.shortcuts import get_object_or_404
from rest_framework import viewsets, mixins
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework import status
from .models import ContractUser
from .serializers import ContractUserSerializer

class ContractUserCreateRetrieveViewSet(
    serializer_class = ContractUserSerializer
    queryset = ContractUser.objects.all()

    def retrieve(self, request, pk):
        permission_classes = [IsAuthenticated]
        queryset = ContractUser.objects.filter(
        user = get_object_or_404(queryset, pk=pk)
        serializer = ContractUserSerializer(user)
        return Response(

    def create(self, request):
        serializer = ContractUserSerializer(
        if serializer.is_valid():
            return Response(, status=status.HTTP_201_CREATED)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

To make the newly created user inactive, I used the pre_save signal. For this purpose, I created a new file in the users application, i.e.

from django.db.models.signals import pre_save
from .models import ContractUser
from django.dispatch import receiver

@receiver(pre_save, sender=ContractUser)
def create_inactive_user(sender, instance, **kwargs):
    instance.is_active = False

The signal should be imported in the ready() function of the UsersConfig() class from the file:

from django.apps import AppConfig

class UsersConfig(AppConfig):
    default_auto_field = "django.db.models.BigAutoField"
    name = "users"

    def ready(self):
        import users.signals

Leave a Reply

Your email address will not be published. Required fields are marked *

− three = two