AttributeError: 'AnonymousUser' object has no attribute '_meta' error using a custom registration form

Viewed 1111

Good Day! I'm trying to make the user of my website register and login with only the email, but I'm getting this error:

AttributeError: 'AnonymousUser' object has no attribute '_meta'

Even if I've this error the account is saved in the database, but I can't login (I've the same error for both registration and login). This is my code:

views.py

def register_view(request, *args, **kwargs):
    user =request.user
    if user.is_authenticated:
        return HttpResponse(f"You are already authenticated as {user.email}.")
    context = {}

    if request.method == 'POST':
        form = RegistrationForm(request.POST)
        if form.is_valid():
            form.save()
            email = form.cleaned_data.get('email').lower()
            raw_password = form.cleaned_data.get('password1')
            account = authenticate(email=email, password=raw_password)
            login(request, account, backend= 'django.contrib.auth.backends.AllowAllUsersModelBackend')
            destination = get_redirect_if_exists(request)
            if destination:
                return redirect(destination)
            return redirect("home") 
        else: 
            context['registration_form'] = form

    return render(request, 'registration/register.html', context)

def logout_view(request):
    logout(request)
    return redirect("home")

def login_view(request, *args, **kwargs):

    context = {}

    user = request.user
    if user.is_authenticated:
        return redirect("home")
    
    if request.POST:
        form = AccountAuthenticationForm(request.POST)
        if form.is_valid():
            email = request.POST['email']
            password = request.POST['password']
            user =authenticate(email=email, password=password)
        if user:
            login(request, user, backend= 'django.contrib.auth.backends.AllowAllUsersModelBackend')
            destination = get_redirect_if_exists(request)
            if destination:
                return redirect(destination)
            return redirect("home") 
        else:
            context['login_form'] = form
    return render(request, "registration/login.html", context)


def get_redirect_if_exist(request):
    redirect = None
    if request.GET:
        if request.GET.get("next"):
            redirect = str(request.GET.get("next"))
    return redirect

Also this is not the first error I'm getting, so I was wondering it this is actually a good code to do what I want or should I restart trying another way. Thank you

EDIT: I added the traceback of the error and also my admin.py and setting.py file since it seems that issue may be in this part (but I still have no idea how to solve it. Thank you again!

Environment:

Request Method: POST
Request URL: http://localhost:8000/main_page/register/

Django Version: 3.2.3
Python Version: 3.8.5
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'main_page']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']

Traceback (most recent call last):
  File "C:\Users\Programs\Python\Python38-32\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
    response = get_response(request)
  File "C:\Users\Programs\Python\Python38-32\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "D:\website\main_page\views.py", line 32, in register_view
    login(request, account, backend= 'django.contrib.auth.backends.AllowAllUsersModelBackend')
  File "C:\Users\Programs\Python\Python38-32\lib\site-packages\django\contrib\auth\__init__.py", line 129, in login
    request.session[SESSION_KEY] = user._meta.pk.value_to_string(user)
  File "C:\Users\Programs\Python\Python38-32\lib\site-packages\django\utils\functional.py", line 247, in inner
    return func(self._wrapped, *args)

Exception Type: AttributeError at /main_page/register/
Exception Value: 'AnonymousUser' object has no attribute '_meta'

admin.py

class AccountAdmin(UserAdmin):
    list_display = ('email', 'date_joined', 'last_login', 'is_admin', 'is_staff')
    ordering = ('email',)
    search_field = ('email')
    #readonly_fields = ('id', 'data_joined', 'last_login')

    filter_horizontal = ()
    list_filter = ()
    fieldsets = ()

admin.site.register(Account, AccountAdmin)

setting.py

ALLOWED_HOSTS = []

AUTH_USER_MODELS = "main_page.Account"
AUTHENTICATION_BACKENDS = (
    'django.contrib.auth.backends.AllowAllUsersModelBackend',
    'main_page.backends.CaseInsensitiveModelBackend'
    )

forms.py

class RegistrationForm(UserCreationForm):

    email = forms.EmailField(max_length=255, help_text="Required. Add a valid email adress.")

    class Meta:
        model = Account
        fields = ('email', 'password1', 'password2')

    def clean_email(self):
        email = self.cleaned_data['email'].lower()
        try:
            account = Account.objects.get(email=email)
        except Exception as e:
            return email
        raise forms.ValidationError(f"Email {email} is alaready in use.") 

class AccountAuthenticationForm(forms.ModelForm):

    password = forms.CharField(label=("password"), widget=forms.PasswordInput)

    class Meta:
        model = Account
        fields = ('email', 'password')

    def clean(self):
        if self.is_valid():
            email = self.cleaned_data['email']
            password = self.cleaned_data['password']
            if not authenticate(email=email, password=password):
                raise forms.ValidationError("Invalid Login")
2 Answers

If the form is invalid, user will still have the AnonymousUser, and thus this will be used in the login call. You should only check if user in case the form was valid:

def login_view(request, *args, **kwargs):

    context = {}

    user = request.user
    if user.is_authenticated:
        return redirect("home")
    
    if request.POST:
        form = AccountAuthenticationForm(request.POST)
        if form.is_valid():
            email = request.POST['email']
            password = request.POST['password']
            user =authenticate(email=email, password=password)
            if user:
                login(request, user, backend= 'django.contrib.auth.backends.AllowAllUsersModelBackend')
                destination = get_redirect_if_exists(request)
                if destination:
                    return redirect(destination)
            return redirect("home") 
        else:
            context['login_form'] = form
    return render(request, "registration/login.html", context)

Try changing:

raw_password = form.cleaned_data.get('password1')

into

raw_password = form.cleaned_data.get('password')
Related