Django: "Не удается преобразовать ключевое слово 'email' в поле. Варианты: created_at, expires_at, id, otp, user, user_id".
Я пытаюсь проверить OTP, который был отправлен пользователю при регистрации. У меня есть отдельная модель для otp, которая имеет отношение OneToOne с пользователем
Otp Model
class Verify(models.Model):
user = models.ForeignKey(
User, on_delete=models.CASCADE, related_name="userverify", blank=False, null=True)
otp = IntegerRangeField(
min_value=111111, max_value=999999, blank=True, null=True)
created_at = models.DateTimeField(
_("created at"), auto_now=False, auto_now_add=True, blank=False)
expires_at = models.TimeField(null=True)
VerifySerializer: Я не указываю модель, потому что она нужна мне только для проверки достоверности входных данных, хотя я думаю, что это может быть проблемой
class VerifySerializerBase(serializers.Serializer):
email = serializers.EmailField()
otp = serializers.CharField()
представление Verify_Email принимает email и значение otp для проверки email
Как я пытаюсь проверить otp
class Verify_Email(APIView):
def post(self, request):
try:
data = request.data
serializer = VerifySerializerBase(data=data)
if serializer.is_valid():
email = serializer.data['email']
otp = serializer.data['otp']
verify = Verify.objects.filter(email=email, otp=otp)
user = User.objects.filter(email=email)
if not user[0].exists():
return Response({
'message': "A user with this email was not found"
}, status=status.HTTP_400_BAD_REQUEST)
elif user[0].is_active:
return Response({
'message': "This email has already been verified"
}, status=status.HTTP_400_BAD_REQUEST)
elif verify[0].exists():
if verify[0].expires_at >= datetime.now():
return Response({
'message': "This OTP has expired, please request another one"
}, status=status.HTTP_400_BAD_REQUEST)
elif verify[0].otp != otp:
return Response({
'message': "This OTP is invalid"
}, status=status.HTTP_400_BAD_REQUEST)
else:
verify[0].delete()
user[0].is_active = True
user[0].save()
return Response({
'message': "Email has been verified"
}, status=status.HTTP_200_OK)
return Response({
'message': "Something is wrong"
}, status=status.HTTP_400_BAD_REQUEST)
return Response({
'message': "Something is wrong"
}, status=status.HTTP_400_BAD_REQUEST)
except Exception as e:
return Response(str(e), status=status.HTTP_404_NOT_FOUND, template_name=None, content_type=None)
и при тестировании я получаю
"Cannot resolve keyword 'email' into field. Choices are: created_at, expires_at, id, otp, user, user_id"
Из того, что я понимаю, я думаю, что это говорит мне, что я проверяю поля, которых нет в полях модели OTP, но я не думаю, что я делаю это?
Ошибка относится к моделям, а не к сериализатору. Эта строка подразумевает, что модель Verify
имеет поле email
, поскольку вы строите запрос на этом поле:
verify = Verify.objects.filter(email=email, otp=otp)
Возможно, вы имели в виду запрос по пользователю, что предполагает замену следующей строки следующим образом:
user = User.objects.get(email=email)
verify = Verify.objects.filter(user=user, otp=otp)
я думаю, что ответ Даниэля правильный, но немного неточный вместо этого используйте
user = User.objects.get(email=email)
можно использовать
user = User.objects.filter(email=email).first()
if user is None:
raise Exception("")
Это лучше, потому что вы можете использовать свой собственный обработчик ошибок другая проблема возникает в вашей модели, если у вас есть дублированный или более otp код в этой ситуации ваш набор запросов выглядит как
verify = Verify.objects.filter(user=user, otp=otp)
возвращает список проверяемых объектов, очевидно, что это не лучшее решение. измените модель следующим образом
class Verify(models.Model):
user = models.ForeignKey(
User, on_delete=models.CASCADE,
related_name="userverify",
blank=False,
null=True
)
otp = IntegerRangeField(
min_value=111111, max_value=999999, blank=True, null=True
)
created_at = models.DateTimeField(
_("created at"), auto_now=False, auto_now_add=True, blank=False
)
expires_at = models.TimeField(null=True)
is_active = models.BooleanField(default=True)
теперь используйте
verify = Verify.objects.filter(user=user, otp=otp, is_active=True)