Каждый раз создаются новые объекты
Я сделал одну функцию для регистрации и входа с помощью мобильного и otp. Регистрационная часть находится в else части функции, а if часть - это функция входа. Каждый раз, когда я вхожу в систему с уже зарегистрированным номером, создается новый объект в базе данных, а я этого не хочу. Я хочу просто обновить часть otp с того момента, когда номер был зарегистрирован в базе данных.
views.py
class RegistrationAPIView(APIView):
permission_classes = (AllowAny,)
serializer_class = ProfileSerializer
def post(self, request):
mobile = request.data['mobile']
data = Profile.objects.filter(mobile = mobile).first()
if data:
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)
serializers.py
class ProfileSerializer(serializers.ModelSerializer):
class Meta:
model = Profile
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.otp = str(random.randint(1000 , 9999))
instance.save()
return instance
Я предполагаю, что вы используете DRF Serializers. Если это так, обратите внимание из документации, что :
Вызов .save() либо создаст новый экземпляр, либо обновит существующий, в зависимости от того, был ли передан существующий экземпляр при инстанцировании класса сериализатора:
# .save() will create a new instance. serializer = CommentSerializer(data=data) # .save() will update the existing `comment` instance. serializer = CommentSerializer(comment, data=data)
В качестве дополнения, вы, вероятно, хотите сделать get_or_create или create_or_update с defaults вместо того, чтобы использовать предложение if/else.
Вариант A: Прежде всего. Если для каждого профиля существует только и исключительно один номер мобильного телефона, вы должны добавить уникальное ограничение и для модели профиля. Что-то вроде:
class Profile(models.Model):
mobile = models.CharField(max_length=20, unique=True)
otp = models.CharField(max_length=6)
Не забудьте сделать миграцию и перенести эти новые изменения в вашу базу данных (также обратите внимание, что в таблице Profile могут быть некоторые дублирующиеся записи, поэтому если вы не на рабочем сервере, сначала удалите все записи, а затем сделайте миграцию).
А затем внесите следующее изменение в метод create вашего сериализатора:
def create(self, 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, defualts=dict(otp=str(random.randint(1000 , 9999))))[0]
return instance
с update_or_create теперь вы уверены, что если запись с определенным мобильным телефоном существует, то вы обновите ее, а если нет, то создадите новую.
Вариант B: Но если вы по каким-либо причинам не хотите вносить это изменение в вашу базу данных, вы можете просто сделать следующее:
def create(self, validated_data):
global totp
secret = pyotp.random_base32()
totp = pyotp.TOTP(secret, interval=300)
otp = totp.now()
if self.Meta.model.objects.filter(**validated_data).exists():
instance = Profile.objects.filter(**validated_data).last()
instance.otp = str(random.randint(1000 , 9999))
instance.save()
else:
instance = self.Meta.model(**validated_data)
instance.otp = str(random.randint(1000 , 9999))
instance.save()
return instance
Обратите внимание, что в вашей таблице может быть несколько записей с одним и тем же номером мобильного телефона, если на эту модель не наложено никаких ограничений. Надеюсь, эти два варианта решат вашу проблему.