Django OTP登录触发last_login字段ValueError问题求助
我在实现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实例。
解决方案
修正获取用户实例的逻辑:
从User_Profile关联的User模型中拿到正确的用户对象,替换错误的查询行:# 替换原来错误的查询代码 user = User.objects.get(id=user_profile.User_id) # 调用login时传入正确的User实例 login(request, user)检查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) # 其他扩展字段...移除自定义User模型中重复的last_login字段:
AbstractUser已经自带last_login字段,重复定义会导致字段冲突,直接删除自定义User模型中的last_login = models.DateTimeField(blank=True, null=True)这一行即可。
内容的提问来源于stack exchange,提问作者Rishi Goyal

