0

我正在使用djangorestframework-simplejwt身份验证。我的用例要求我使用 OTP 而不是密码。

为了存储 OTP,我创建了以下模型:

class OneTimePassword(models.Model):
    otp = models.IntegerField()
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

用户型号:

class User(AbstractUser):

    username = None
    email = models.EmailField(_('email address'), unique=True)
    country_code = models.IntegerField(default=91, max_length=3)
    mobile = models.IntegerField(max_length=11, unique=True)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['mobile']

    objects = CustomUserManager()

    def __str__(self):
        return f"{self.email},{self.mobile}"

我的计划是:

  1. POSTmobile/api/generate_otp/端点
  2. 在此端点的视图中,会生成一个新的 OTP 并将其存储在OneTimePassword模型中。(用户由手机号确定)
  3. api/token/obtain/端点,OTP 和手机号码被张贴。
  4. 如果 OTP 与存储在 OTP 模型中的值匹配,则返回 JWT 令牌。

我在步骤 2中遇到困难,即我无法通过用户更新 OneTimePassword 模型中的 OTP 值。

我尝试了以下方法:

class GenerateOTPMobileView(APIView):
    permission_classes = ()

    def post(self, request,):
        mobile = request.data.get("mobile")
        user = User.objects.get(mobile=mobile)
        random_otp = randint(10000, 99999)
        if user:
            user.onetimepassword_set.otp = random_otp   # This is not working
            ...
            # send OTP through third party API
            ...
            return Response({"success": "OTP sent to mobile number"},)
        else:
            return Response({"error": "Wrong Credentials"}, status=status.HTTP_400_BAD_REQUEST)

4

1 回答 1

0

您正在尝试在关系的多方面设置属性,但它不起作用。基本上,您只是在管理器上设置一个属性,而管理器就像任何其他表现良好的 python 对象一样,只会在其自身上设置此属性 - 但它没有做任何有用的事情。

相反,您应该使用create()新的 OTP 或update()特定的 OTP。

请记住,您的数据模型如下所示:

user:
   - otp1
   - otp2
   - otp3  

等等

所以没有“一个用户一个 OTP”。为此,您需要一个 OneToOneField。

于 2020-07-22T18:51:33.037 回答