自定义AuthenticationForm登录不存在账户时触发AnonymousUser无_meta属性错误
Django自定义AuthenticationForm登录不存在账户触发AttributeError问题解决
问题现象
使用自定义AuthenticationForm登录不存在的账户时,触发如下错误:
File "C:\python\CTFp\.venv\Lib\site-packages\django\utils\functional.py", line 253, in inner return func(_wrapped, *args) ^^^^^^^^^^^^^^^^^^^^^ AttributeError: 'AnonymousUser' object has no attribute '_meta'
登录已存在的账户时无此错误,切换为基础AuthenticationForm后错误消失。
相关代码
forms.py
class AuthenticationForm(BaseAuthenticationForm): def clean(self): username = self.cleaned_data.get("username") password = self.cleaned_data.get("password") ogg = User.objects.filter(Q(email=username) or Q(username=username)).first() if ogg is not None and password: self.user_cache = authenticate( self.request, username=ogg.username, password=password ) if self.user_cache is None: raise self.get_invalid_login_error() else: self.confirm_login_allowed(self.user_cache) return self.cleaned_data
urls.py
urlpatterns = [path('signin', views.LoginView.as_view(authentication_form=forms.AuthenticationForm), {'template_name': 'users/signin.html'}, name='signin'),]
models.py
class User(AbstractUser): challenges = models.ManyToManyField(Challenge)
问题原因
- 逻辑漏洞:当登录的账户不存在时(
ogg为None),自定义clean方法未设置self.user_cache,此时Django默认将其设为AnonymousUser。而LoginView后续处理会尝试访问用户模型的_meta属性,AnonymousUser并非Django数据库模型,没有该属性,从而触发错误。 - 查询条件错误:原代码中使用
Q(email=username) or Q(username=username)是错误的,Python逻辑运算符or会将Q对象转换为布尔值,导致实际查询条件失效,可能引发意外的用户匹配结果。
解决方案
修改自定义AuthenticationForm的clean方法,完善验证逻辑并修正查询条件:
class AuthenticationForm(BaseAuthenticationForm): def clean(self): username = self.cleaned_data.get("username") password = self.cleaned_data.get("password") if username and password: # 使用Django查询位运算符|同时匹配邮箱和用户名 user = User.objects.filter( Q(email=username) | Q(username=username) ).first() if not user: # 用户不存在时直接抛出登录错误 raise self.get_invalid_login_error() self.user_cache = authenticate( self.request, username=user.username, password=password ) if self.user_cache is None: raise self.get_invalid_login_error() else: self.confirm_login_allowed(self.user_cache) return self.cleaned_data
关键修改说明
- 先校验
username和password均存在,再执行后续逻辑 - 用户不存在时立即抛出登录错误,避免
user_cache处于未初始化状态 - 将查询条件中的
or替换为Django查询专用的|,确保多条件匹配逻辑正确
内容的提问来源于stack exchange,提问作者Pikabo
相关产品推荐
相关产品推荐

