فایل view به شرح زیر است

from django.contrib.auth import get_user_model
from rest_framework import viewsets, status
from rest_framework.response import Response
from rest_framework_simplejwt.tokens import RefreshToken
from app_account.models import CustomUser
from app_account.serializers import UserSerializer, RequestOTPSerializer, VerifyOtpRequestSerializer, ObtainTokenSerializer
from rest_framework.decorators import action
import random
import string
from django.core.cache import cache
from .msg_sender import send_otp
from datetime import datetime, time, timedelta
from .models import DeviceFingerprint
from rest_framework.exceptions import ValidationError

# region ==> OTP

def get_difference_secound():
    # گرفتن زمان فعلی
    now = datetime.now()

    # تعیین زمان نیمه‌شب (ساعت 12 شب)
    midnight = datetime.combine(now.date(), time(0, 0))

    # اگر زمان فعلی بعد از نیمه‌شب است (در روز بعد) زمان نیمه‌شب روز بعد را بگیرید
    if now > midnight:
        midnight = datetime.combine(now.date() + timedelta(days=1), time(0, 0))

    # محاسبه اختلاف زمان
    difference = midnight - now
    sec_difference = int(difference.total_seconds()//1)

    return sec_difference - 10

def set_data_dic(data):

    if isinstance(data, dict):
        body_data = data
    else:
        body_data = data.dict()

    return body_data

class OTPViewSet(viewsets.ViewSet):

    @action(detail=False, methods=['post'])
    def request_otp(self, request):
        body_data = set_data_dic(request.data)
        serializer = RequestOTPSerializer(data=body_data)
        
        if serializer.is_valid():
            data = serializer.validated_data

            # جستجوی کاربر با کد ملی
            existing_user = CustomUser.objects.filter(username=data['national_id']).first()
            print(existing_user.phone_number)
            if existing_user and existing_user.phone_number != data['phone_num']:
                raise ValidationError({
                    'status': 'PHONE_NUMBER_DIFFERENT',
                    'message': 'این کد ملی قبلاً با یک شماره تلفن دیگر ثبت‌نام شده است.',
                })
            
            # ادامه روند
            otp = self._generate_otp()
            counter_otp = cache.get(f"otp_{data['phone_num']}_count")
            if counter_otp is None:
                cache.set(f"otp_{data['phone_num']}_count", 1, timeout=get_difference_secound())
            elif counter_otp is not None:
                if counter_otp <= 500:
                    cache.set(f"otp_{data['phone_num']}_count", counter_otp+1, timeout=get_difference_secound())
                else:
                    return Response({
                        'status': 'LIMIT_REACHED',
                        'message': 'شما به محدودیت تعداد کد در امروز رسیده‌اید. لطفاً فردا دوباره تلاش کنید.',
                        'suggestion': 'در صورت نیاز مبرم به دریافت کد، با پشتیبانی تماس بگیرید.',
                        'phone_num': data['phone_num']
                    }, status=status.HTTP_429_TOO_MANY_REQUESTS)
            
            # ذخیره و ارسال OTP
            cache.set(f"otp_{data['phone_num']}", otp, timeout=120)
            # send_otp(phone_number=data['phone_num'], password=otp)
            print(data['phone_num'], otp)
            
            return Response({
                'status': 'OTP_SENT',
                'message': 'کد تأیید با موفقیت ارسال شد.',
                'phone_num': data['phone_num']
            }, status=status.HTTP_200_OK)

        # نمایش خطاهای ولیدیشن سریالایزر
        return Response({
            'status': 'BAD_REQUEST',
            'errors': serializer.errors
        }, status=status.HTTP_400_BAD_REQUEST)
    
    @action(detail=False, methods=['post'])
    def verify_otp(self, request):
        
        body_data = set_data_dic(request.data)

        # فرض کنید فینگرپرینت از درخواست دریافت شود

        serializer = VerifyOtpRequestSerializer(data=body_data)
        if serializer.is_valid():
            data = serializer.validated_data
            cached_otp = cache.get(f"otp_{data['phone_num']}")

            if cached_otp and cached_otp == data['password']:
                user, created = self._get_or_create_user(data['national_id'])

                # اعتبارسنجی فینگرپرینت دستگاه
                if data['uniq_id_device'] in user.device_fingerprints.all():
                    token_data = self._generate_tokens_for_user(user, created)
                    
                    return Response({
                        'status': 'SUCCESS',
                        'message': 'کد تأیید صحیح است و شما با موفقیت وارد سیستم شدید.',
                        'user_data': token_data
                    }, status=status.HTTP_200_OK)
                
                elif len(user.device_fingerprints.all()) < 3:
                    fingerprint, created = DeviceFingerprint.objects.get_or_create(
                    user=user,
                    fingerprints=data['uniq_id_device']
                    )
                    if created:
                        fingerprint.save()
                        
                    token_data = self._generate_tokens_for_user(user, created)

                    return Response({
                        'status': 'SUCCESS_WITH_NEW_DEVICE',
                        'message': 'ورود موفق بود و دستگاه جدید اضافه شد.',
                        'user_data': token_data
                    }, status=status.HTTP_200_OK)

                else:
                    return Response({
                        'status': 'DEVICE_LIMIT_REACHED',
                        'message': 'شما به محدودیت دستگاه‌ رسیده‌اید. لطفاً ابتدا دستگاه دیگری را حذف کنید.',
                    }, status=status.HTTP_403_FORBIDDEN)

            return Response({
                'status': 'INVALID_OTP',
                'message': 'کد وارد شده نادرست است. لطفاً مجدد تلاش کنید.',
            }, status=status.HTTP_401_UNAUTHORIZED)

        # گسیل خطاهای ولیدیشن سریالایزر
        return Response({
            'status': 'BAD_REQUEST',
            'message': 'درخواست نامعتبر است. لطفاً خطاها را اصلاح کرده و مجدد تلاش کنید.',
            'errors': serializer.errors
        }, status=status.HTTP_400_BAD_REQUEST)

    def _get_or_create_user(self, national_id):
        User = get_user_model()
        user, created = User.objects.get_or_create(username=national_id)
        return user, created

    def _generate_tokens_for_user(self, user, created):
        refresh = RefreshToken.for_user(user)
        return ObtainTokenSerializer({
            'refresh': str(refresh),
            'token': str(refresh.access_token),
            'created': created
        }).data
    
    def _generate_otp(self):
        return ''.join(random.choices(string.digits, k=4))
    
class UsersViewSetApiView(viewsets.ModelViewSet):
    queryset = CustomUser.objects.all()
    serializer_class = UserSerializer

فایل مدل هام به شرح زیر است 

from django.db import models
from django.contrib.auth.models import AbstractUser
from django.utils import timezone
import uuid
import random
import string
from datetime import timedelta
from app_account.msg_sender import send_otp


# region ==> Custom User Model
class CustomUser(AbstractUser):
    
    class GenderChoices(models.TextChoices):
        MALE = 'male', "مرد"
        FEMALE = 'female', "زن"
        OTHER = 'other', "دیگر"

    username = models.CharField(
        max_length=10, 
        unique=True, 
        verbose_name='کد ملی'
    )
    first_name = models.CharField(
        max_length=20, 
        blank=True, 
        null=True, 
        verbose_name='نام'
    )
    last_name = models.CharField(
        max_length=40, 
        blank=True, 
        null=True, 
        verbose_name='نام خانوادگی'
    )
    phone_number = models.CharField(
        max_length=11, 
        blank=True, 
        null=True,
        verbose_name='شماره همراه'
    )
    gender = models.CharField(
        max_length=6, 
        blank=True, 
        null=True, 
        choices=GenderChoices.choices, 
        verbose_name='جنسیت'
    )
    birth_date = models.DateField(
        blank=True, 
        null=True, 
        verbose_name='تاریخ تولد'
    )

    def __str__(self) -> str:
        return f"{self.first_name} {self.last_name}"

    class Meta:
        db_table = 'tbl_user_info'
        verbose_name_plural = 'مشخصات کاربران'
# endregion

class DeviceFingerprint(models.Model):
    user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name='device_fingerprints')
    fingerprints = models.CharField(max_length=50, blank=True, null=True, verbose_name='دستگاه')

    def __str__(self) -> str:
        return f"{self.user} {self.fingerprints}"

    class Meta:
        db_table = 'tbl_user_devices_info'
        verbose_name_plural = 'آیدی دستگاه های کاربران'

# region ==> OTP
class OtpRequestQuerySet(models.QuerySet):
    
    def is_valid(self, national_id, phone_num, request, password):
        current_time = timezone.now()
        valid_time_range = current_time - timedelta(seconds=120)
        return self.filter(
            national_id=national_id,
            phone_num=phone_num,
            request_id=request,
            password=password,
            created__lt=current_time,
            created__gt=valid_time_range
        ).exists()


class OTPManager(models.Manager):
    
    def get_queryset(self):
        return OtpRequestQuerySet(self.model, self._db)

    def is_valid(self, national_id, phone_num, request, password):
        return self.get_queryset().is_valid(national_id, phone_num, request, password)
    
    def generate(self, data):
        otp = self.model(
            channel=data['channel'], 
            national_id=data['national_id'], 
            phone_num=data['phone_num']
        )
        otp.save(using=self._db)
        send_otp(otp)
        return otp


def generate_otp():
    rand = random.SystemRandom()
    digits = rand.choices(string.digits, k=4)
    return ''.join(digits)


# endregion


شماره تلفن کاربر رو ذخیره نمیکنه
چیکار کنم ؟