You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django OTP登录触发last_login字段ValueError问题求助

问题:OTP登录调用login()时触发last_login字段错误

我在实现OTP用户登录功能时,验证OTP有效性后调用login(request, user)方法触发错误,报错信息:

ValueError: The following fields do not exist in this model, are m2m fields, or are non-concrete fields: last_login

已在自定义User模型中添加last_login字段,但问题仍未解决。


相关代码

视图中login_otp方法的POST处理逻辑

if request.method == "POST":
        mobile_number=request.session['mobile_number']
        print(mobile_number)
        otp=request.POST.get('otp')

        try:
            user_profile=User_Profile.objects.get(Phone=mobile_number)
            print(user_profile.Otp)
            
        except ObjectDoesNotExist:
            messages.error(request,"Invalid mobile nummber")
            return redirect('login_with_otp')

        if otp!=str(user_profile.Otp):
            print(type(otp))
            print(type(user_profile.Otp))
            print(otp)
            print(user_profile.Otp)
            messages.error(request,"Invalid OTP oh")
            return redirect('login_with_otp')

        user_profile.Otp=None
        user_profile.save()
        print(user_profile.id)
        user_profile = User_Profile.objects.get(Email=user_profile.User_id)
        print("user object : ",type(user_profile))
        print(user_profile)
        login(request,user_profile)
        messages.success(request,"You are now logged in")
        return redirect('home')

自定义User模型

class User(AbstractUser):
    email = models.EmailField(max_length=75, unique=True)
    username= models.CharField(max_length=75)
    first_name = models.CharField(max_length=75, null=True, blank=True)
    last_name = models.CharField(max_length=75, null=True, blank=True)
    email_verified = models.BooleanField(default=False)
    last_login = models.DateTimeField(blank=True, null=True)
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS= ['username']

错误溯源

错误来自Django auth模型的这一行代码:

# File "C:\Users\rishi\Desktop\Hosted surginatal\env\Lib\site-packages\django\contrib\auth\models.py", line 23
user.save(update_fields=["last_login"])

问题原因

你传给login()方法的不是自定义的User模型实例,而是User_Profile实例。Django的login()函数要求接收继承自AbstractBaseUser或AbstractUser的用户模型对象,但你最后获取的user_profile是关联用户的扩展表模型,它本身没有last_login字段,所以update_last_login信号触发时直接报错。

看代码里的错误逻辑:

user_profile = User_Profile.objects.get(Email=user_profile.User_id)

这里用User_id(关联User模型的外键)去匹配User_Profile的Email字段,最后拿到的还是User_Profile对象,完全没获取到真正的User实例。


解决方案

  1. 修正获取用户实例的逻辑:
    从User_Profile关联的User模型中拿到正确的用户对象,替换错误的查询行:

    # 替换原来错误的查询代码
    user = User.objects.get(id=user_profile.User_id)
    # 调用login时传入正确的User实例
    login(request, user)
    
  2. 检查User_Profile模型的关联字段:
    确保User_Profile模型中有正确关联自定义User的外键,比如:

    class User_Profile(models.Model):
        User_id = models.ForeignKey(User, on_delete=models.CASCADE)
        Phone = models.CharField(max_length=15)
        Otp = models.CharField(max_length=6, null=True, blank=True)
        # 其他扩展字段...
    
  3. 移除自定义User模型中重复的last_login字段:
    AbstractUser已经自带last_login字段,重复定义会导致字段冲突,直接删除自定义User模型中的last_login = models.DateTimeField(blank=True, null=True)这一行即可。


内容的提问来源于stack exchange,提问作者Rishi Goyal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 23:43:31