Search code examples
pythondjangodjango-authentication

Django Authentication Form not working properly


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.


Solution

  • The Django AuthenticationForm takes a request object as its first argument. You can provide submitted data like request.POST as the data kwarg

    auth_form = AuthenticationForm(None, data=request.POST)