پروژه ای دارم به شرح زیر

فایل view.py

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

# 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


class OTPViewSet(viewsets.ViewSet):

    @action(detail=False, methods=['post'])
    def request_otp(self, request):
        serializer = RequestOTPSerializer(data=request.data)
        if serializer.is_valid():
            data = serializer.validated_data
            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 <= 5:
                    cache.set(f"otp_{data['phone_num']}_count", counter_otp+1, timeout=get_difference_secound())
                else:
                    return Response({'error': 'شما به محدودیت تعداد کد در امروز رسیده اید'},status=status.HTTP_406_NOT_ACCEPTABLE)    
            cache.set(f"otp_{data['phone_num']}", otp, timeout=120)
            send_otp(phone_number=data['phone_num'], password=otp)
            return Response(status=status.HTTP_200_OK)

        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        
    @action(detail=False, methods=['post'])
    def verify_otp(self, request):
        serializer = VerifyOtpRequestSerializer(data=request.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']:
                # کد تایید صحیح است
                cache.delete(f"otp_{data['phone_num']}")
                return Response(self._handle_login(data['national_id']), status=status.HTTP_200_OK)

            return Response({'error': 'کد وارد شده نادرست است'}, status=status.HTTP_401_UNAUTHORIZED)

        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def _handle_login(self, national_id):
        User = get_user_model()
        query = User.objects.filter(username=national_id)
        created = False
        if query.exists():
            user = query.first()
        else:
            # ایجاد کاربر جدید
            user = User.objects.create(username=national_id)
            created = True

        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