Login,register and verify OTP API project with Django rest framework

I want to make an API project in which a person can Login, register with a phone number and OTP.

What we need to do in this project

  1. Login and Register from the same page.
  2. Verify OTP from verify image.
  3. When user gets register for the first time mobile number, otp, a random username,a random picture from a folder,a random profile id, a name whic is the same as mobile number gets alloted in the database.

Here's my code

modals.py

class User(models.Model):
    mobile = models.CharField(max_length=20)
    otp = models.CharField(max_length=6)
    name = models.CharField(max_length=200)
    username = models.CharField(max_length=200)
    logo = models.FileField(upload_to ='profile/')
    profile_id = models.CharField(max_length=200)

serializers.py

class ProfileSerializer(serializers.ModelSerializer):
       class Meta:
           model = User
           fields = ['mobile']
       def create(self, validated_data):
                
                    instance = self.Meta.model(**validated_data)
                    global totp
                    secret = pyotp.random_base32()
                    totp = pyotp.TOTP(secret, interval=300)
                    otp = totp.now()
                    instance = self.Meta.model.objects.update_or_create(**validated_data, defaults=dict(otp=str(random.randint(1000 , 9999))))[0]            
                    instance.save()
                    return instance
    
    class VerifyOTPSerializer(serializers.ModelSerializer):
        
        class Meta:
            model = User
            fields = ['mobile','otp']
            
        def create(self,validated_data):
            
            instance = self.Meta.model(**validated_data)
            mywords = "123456789"
            res = "expert@" + str(''.join(random.choices(mywords,k = 6)))
            path = os.path.join(BASE_DIR, 'static')
            dir_list = os.listdir(path)
            random_logo = random.choice(dir_list)
            instance = self.Meta.model.objects.update_or_create(**validated_data, defaults = dict(username = res,name = instance.mobile ,logo = random_logo, profile_id = res))[0]
            instance.save()
            return instance

views.py

def send_otp(mobile,otp):
    url = "https://www.fast2sms.com/dev/bulkV2"
    authkey = settings.AUTH_KEY
    querystring = {"authorization":authkey,"variables_values":otp,"route":"otp","numbers":mobile}
    headers = {
        'cache-control': "no-cache"
    }
    response = requests.request("GET", url, headers=headers, params=querystring)
    print(response.text)


class RegistrationAPIView(APIView):
    permission_classes = (AllowAny,)
    serializer_class = ProfileSerializer

    def post(self, request):
        mobile = request.data['mobile']
        data = User.objects.filter(mobile = mobile).first()
        if data is not None:
            serializer = self.serializer_class(data=request.data)
            mobile = request.data['mobile']
            if serializer.is_valid(raise_exception=True):
                instance = serializer.save()
                content = {'mobile': instance.mobile, 'otp': instance.otp}
                mobile = instance.mobile
                otp = instance.otp
                print("Success")
                send_otp(mobile,otp)
                return Response(content, status=status.HTTP_201_CREATED)
            else:
                return Response({"Error": "Login in Failed"}, status=status.HTTP_400_BAD_REQUEST)
        else:
            serializer = self.serializer_class(data=request.data)
            mobile = request.data['mobile']
            if serializer.is_valid(raise_exception=True):
               
                instance = serializer.save()
                content = {'mobile': instance.mobile, 'otp': instance.otp}
                mobile = instance.mobile
                otp = instance.otp
                send_otp(mobile,otp)
                return Response(content, status=status.HTTP_201_CREATED)
            else:
                return Response({"Error": "Sign Up Failed"}, status=status.HTTP_400_BAD_REQUEST)


class VerifyOTPView(APIView):
    permission_classes = (AllowAny,)
    serializer_class = VerifyOTPSerializer

    def post(self, request):
        serializer = VerifyOTPSerializer(data=request.data)
        mobile = request.data['mobile']
        otp_sent = request.data['otp']

        if mobile and otp_sent:
            old = User.objects.filter(mobile=mobile)
            if old is not None:
                old = old.first()
                otp = old.otp
                if str(otp) == str(otp_sent):
                    serializer = self.serializer_class(data=request.data)
                    mobile = request.data['mobile']
                    if serializer.is_valid(raise_exception=True):
                        instance = serializer.save()
                        content = {'mobile': instance.mobile, 'otp': instance.otp, 'name':instance.name, 'username':instance.username, 'logo':instance.logo, 'profile_id': instance.profile_id }
                        return Response(content, status=status.HTTP_201_CREATED)
                else:
                        return Response({
                            'status' : False, 
                            'detail' : 'OTP incorrect, please try again'
                        })

settings.py

STATIC_URL = 'static/'
STATIC_DIR = os.path.join(BASE_DIR, 'static')
STATICFILES_DIRS = [STATIC_DIR]

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

Application's urls.py

path('register/', RegistrationAPIView.as_view()),
    path('verify', VerifyOTPView.as_view()),

Now, there are two problems.

  1. The random image is not getting saved in database i get error of not found.
  2. i am getting all the results i want when i register everything gets alloted fine except images but when i login with the same mobile number all the data gets updated again and i get everything new in the database. i don't want anything updated except otp.Otp should get updated everytime user login with the number but data should remain same as it was alloted at the time of registeration.
Back to Top