Advice on custom user model and custom auth serializers

I need some advice from the devs out there who are experienced in Django. I am relatively new to this framework and am working on a pharmacy management app with a Django-powered backend. I plan to use mobile number as the way to sign up into the app. Most built-in classes provide email as the default way to register and create new users. I am using DRF for the REST API stuff, dj-rest-auth and django-allauth for handling authentication. Right now I am working only on user accounts within the app. Could you please give a check and point out the mistakes. Any advice on the best practices would be appreciated.

Here's the custom user model

from django.contrib.auth.models import AbstractUser
from django.db import models
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from .managers import CustomUserManager
from django.core.validators import RegexValidator

phone_validator = RegexValidator(regex=r"^[1-9]\d{9}$", message="Invalid Number")


class UserRole(models.TextChoices):
    RETAILER = "RETAILER", "retailer"
    STAFF = "STAFF", "staff"


class CustomUser(AbstractUser):
    username = None
    mobile = models.CharField(max_length=10, validators=[phone_validator], unique=True)
    role = models.CharField(
        max_length=20, choices=UserRole.choices, default=UserRole.STAFF
    )
    tenant = models.ForeignKey(
        "tenants.Tenant",
        on_delete=models.CASCADE,
        null=True,
        blank=True,
        related_name="users",
    )
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    objects = CustomUserManager()

    USERNAME_FIELD = "mobile"

    REQUIRED_FIELDS = []

    def __str__(self):
        return f"{self.mobile} ({self.get_full_name()})"

Here are the custom serializers.

from dj_rest_auth.serializers import LoginSerializer
from dj_rest_auth.registration.serializers import RegisterSerializer
from rest_framework import serializers
from allauth.account.adapter import get_adapter


class MobileLoginSerializer(LoginSerializer):
    username = None

    mobile = serializers.CharField(required=True)

    def validate(self, attrs):
        attrs["username"] = attrs.get("mobile")
        return super().validate(attrs)


class MobileRegisterSerializer(RegisterSerializer):
    username = None
    first_name = serializers.CharField()
    last_name = serializers.CharField()
    mobile = serializers.CharField()
    pharmacy_name = serializers.CharField(write_only=True)
    role = serializers.ChoiceField(choices=["RETAILER", "STAFF"])

    def get_cleaned_data(self):
        data = super().get_cleaned_data()
        data.update(
            {
                "first_name": self.validated_data.get("first_name", ""),
                "last_name": self.validated_data.get("last_name", ""),
                "mobile": self.validated_data.get("mobile", ""),
                "pharmacy_name": self.validated_data.get("pharmacy_name", ""),
                "role": self.validated_data.get("role", ""),
            }
        )
        return data

    def save(self, request):
        adapter = get_adapter()
        user = adapter.new_user(request)
        self.cleaned_data = self.get_cleaned_data()

        user = adapter.save_user(request, user, self, commit=False)
        user.first_name = self.cleaned_data.get("first_name")
        user.last_name = self.cleaned_data.get("last_name")
        user.mobile = self.cleaned_data.get("mobile")
        # user.pharmacy_name = self.cleaned_data.get("pharmacy_name")
        user.role = self.cleaned_data.get("role")
        user.save()

        self.custom_signup(request, user)
        return user

Here are the relevant code snippets from settings.py

...
REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": ["dj_rest_auth.jwt_auth.JWTCookieAuthentication"]
}

REST_AUTH = {
    "USE_JWT": True,
    "JWT_AUTH_COOKIE": "access",
    "JWT_AUTH_REFRESH_COOKIE": "refresh",
    "JWT_AUTH_HTTPONLY": True,
    "LOGIN_SERIALIZER": "accounts.serializers.MobileLoginSerializer",
    "REGISTER_SERIALIZER": "accounts.serializers.MobileRegisterSerializer",
}

AUTH_USER_MODEL = "accounts.CustomUser"

ACCOUNT_USER_MODEL_USERNAME_FIELD = "mobile"
ACCOUNT_EMAIL_REQUIRED = False
ACCOUNT_USERNAME_REQUIRED = False
ACCOUNT_AUTHENTICATION_METHOD = "username"

...

SITE_ID = 1

P.S.: I do not trust the AI responses. Different agents are suggesting different approaches and now I am confused.

Вернуться на верх