Authentication Form not working properly.

Hello.

I am trying to create a very basic login system (just to grasp Django’s authentication system, nothing fancy).

Thing is, when I use the following code (i.e. don’t validate authentication form submission), everything works perfectly.

The views.py file:

from django.shortcuts import render, redirect
from django.http import request
from django.contrib.auth.decorators import login_required
from .forms import UserRegistrationForm
from django.contrib import messages
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.forms import AuthenticationForm

@login_required(login_url="accounts/login")
def home(request):
    return render(request, "main/home.html")

def register_user(request):
    if request.method == "POST":
        reg_form = UserRegistrationForm(request.POST)
        if reg_form.is_valid():
            user = reg_form.save()

            messages.success(request, f'You have successfully registered!')
            return redirect("login")
        else:
            messages.error(request, "Some problem occured")
    else:
        reg_form = UserRegistrationForm()
    return render(request, template_name='main/register.html', context={"form":reg_form})
    
def login_view(request):
    if request.method == "POST":
        username = request.POST.get("username")
        password = request.POST.get("password")
        user = authenticate(request, username = username, password = password)

        if user is not None:
            login(request, user)
            messages.success(request, f"You logged in as: {username}")
                    
            return redirect("home")
        else:
            messages.error(request, "Invalid username or password")
            return redirect("login")
    else:
        auth_form = AuthenticationForm()
    return render(request, "registration/login.html", context={"form":auth_form})

def logout_request(request):
    logout(request)
    messages.success(request, f"You have logged out.")
    return redirect("login")

However, when I insert authentication form validation and population, user is not authenticated and None is returned instead.

For the purpose of simplicity I am adding the ‘login_view’ only as this is where I encounter the problem.

def login_view(request):
    if request.method == "POST":
        auth_form = AuthenticationForm(request.POST)
        if auth_form.is_valid():
            username = auth_form.cleaned_data.get("username")
            password = auth_form.cleaned_data.get("password")
            user = authenticate(request, username = username, password = password)

            if user is not None:
                login(request, user)
                messages.success(request, f"You logged in as: {username}")
                    
                return redirect("home")
            else:
                messages.error(request, "Invalid username or password")
                return redirect("login")
        else:
            messages.error(request, f"Some problem encountered.")
            return redirect("login")
    else:
        auth_form = AuthenticationForm()
    return render(request, "registration/login.html", context={"form":auth_form})

NOTE: I know such an if-else ladder is discouraged and shouldn’t be used. But I’m just curious as to why the former solution works and the latter one does not.

Thanks for the help.

It will help you diagnose the errors you are encountering if you print (or render) the errors reported by the form from the is_valid test. See the Form.errors docs.

Ok. So, I entered the print statement (using auth_form.errors.get_data() ) in both the ‘is_valid’ section and the corresponding else statement. It just gives me ‘{}’.

Also, when I insert a print statement in the is_valid section to print the entered username, nothing is printed. And when I add this statement in the corresponding else, the correct username gets printed.

Please post the updated code where you’re trying all this. (I don’t see a get_data method, I see an as_data and a get_json_data, so I would actually expect you to get an error message if that’s what you tried.)

Also note that the clean method of the django.contrib.auth.forms.AuthenticationForm performs the authenticate call - that’s not something you need to do within your view. It also raises its own error messages internally.

I suggest you review how that form works - you’re doing a lot of work here that is trying to replicate what that form already provides.

Yes, I mistook its working to be the same as other Model Forms.

It provides its own authentication mechanism and generates its own errors.

Also, it takes a request parameter (mandatory) and after that we can pass request.POST as data (using kwargs).

Thanks loads for the help :slight_smile: