Объект 'AnonymousUser' не имеет атрибута '_meta' в представлении Login
при использовании пользовательской формы аутентификации возникает ошибка при попытке входа с несуществующей учетной записью, но при использовании существующей учетной записи ошибка не возникает
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'
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)
попытался изменить форму auth на базовую AuthenticationForm и ошибка не возникает.
I think you are trying to fix the problem at the wrong location: the form should not be responsible on how to authenticate, that should the authentication backend do. We can write a custom authentication backend [Django-doc] to work with a username or an email:
# app_name/authentication.py
from django.contrib.auth.backends import BaseBackend
from django.db.models import Q
class UsernameEmailAuthenticationBackend(BaseBackend):
def authenticate(self, request, username=None, password=None):
try:
user = User.objects.get(Q(email=username) | Q(username=username))
except User.DoesNotExist:
return None
if user.check_password(password):
return user
return None
и добавьте это в настройки AUTHENTICATION_BACKENDS [Django-doc]:
# settings.py
# …
AUTHENTICATION_BACKENDS = ['app_name.authentication.UsernameEmailAuthenticationBackend']
Хотя это, вероятно, не самая важная часть, она означает, что пользователь будет получен один раз, в то время как попытка найти имя пользователя в форме вызовет второй запрос.