Объект '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']

Хотя это, вероятно, не самая важная часть, она означает, что пользователь будет получен один раз, в то время как попытка найти имя пользователя в форме вызовет второй запрос.

Вернуться на верх