Django注册系统添加邮箱验证后出现AnonymousUser属性错误
错误根源
触发AttributeError: 'AnonymousUser' object has no attribute 'is_email_verified'的原因很明确:
注册视图的post方法中调用send_action_email时,传入了request.user——此时新用户刚创建还未登录,request.user是Django的匿名用户对象,它没有你自定义的is_email_verified字段;而你的generate_token.make_token(user)方法会读取该字段生成令牌,因此直接报错。
具体修复步骤
1. 修正注册视图:传入刚创建的新用户实例
在PersonalRegister的post方法中,你肯定已经完成了新用户的创建逻辑(代码中省略的...部分),需要将这个刚创建的用户实例传给send_action_email,而非匿名的request.user:
class PersonalRegister(View): def post(self, request, *args, **kwargs): # 从request.POST获取表单数据 username = request.POST.get('username') email = request.POST.get('email') password = request.POST.get('password') # 创建新用户实例(根据你的模型调整字段) new_user = models.PersonalUser.objects.create_user( username=username, email=email, password=password ) # 传入刚创建的new_user,替换原有的request.user send_action_email(new_user, request) # 其他逻辑:比如返回注册成功提示页 return render(request, 'authentication/personal/signup_success.html') def get(self, request, *args, **kwargs): return render(request, 'authentication/personal/personal_signup.html')
2. 修复发送邮件函数的细节问题
当前send_action_email中把models.PersonalUser(模型类)传给了模板,而非用户实例,会导致模板调用用户属性失败;同时current_site需要取domain属性才能正确显示域名:
from .utils import generate_token from django.template.loader import render_to_string from django.core.mail import EmailMessage from django.utils.http import urlsafe_b64encode, force_bytes from django.contrib.sites.shortcuts import get_current_site from django.conf import settings def send_action_email(user, request): current_site = get_current_site(request) email_subject = 'Activate account | Zane' email_body = render_to_string('authentication/email/email_body.html', { 'user': user, # 替换为传入的用户实例 'domain': current_site.domain, # 取domain属性 'uid': urlsafe_b64encode(force_bytes(user.pk)), 'token': generate_token.make_token(user) }) email = EmailMessage(subject=email_subject, body=email_body, from_email=settings.EMAIL_FROM_USER, to=[user.email]) email.send()
3. 限制已登录用户访问注册/登录页面
使用user_passes_test装饰器实现反向限制,只允许未登录用户访问注册和登录页面:
from django.contrib.auth.decorators import user_passes_test from django.utils.decorators import method_decorator # 定义判断用户未登录的函数 def is_not_authenticated(user): return not user.is_authenticated # 给注册视图加装饰器 @method_decorator(user_passes_test(is_not_authenticated), name='dispatch') class PersonalRegister(View): # 原有代码... # 给登录视图加装饰器 @method_decorator(user_passes_test(is_not_authenticated), name='dispatch') class Login(View): # 原有代码...
如果需要自定义重定向地址,可以在user_passes_test中添加login_url参数,比如user_passes_test(is_not_authenticated, login_url='/dashboard/')。
4. 确认用户模型字段正确性
确保你的PersonalUser模型中确实存在is_email_verified字段,且默认值为False:
from django.contrib.auth.models import AbstractUser from django.db import models class PersonalUser(AbstractUser): is_email_verified = models.BooleanField(default=False) # 其他自定义字段...
验证修复效果
完成上述修改后,新用户注册时会直接触发验证邮件发送,点击邮件中的激活链接即可完成邮箱验证;已登录用户访问注册/登录页面会被自动拦截,完全符合需求。
内容的提问来源于stack exchange,提问作者P Studio

