How to display a form error on invalid password input in django?

I have a login form that can display a error message on invalid username input, but I am having trouble figuring out how to display an error on a invalid password input.

The invalid username error

I want to be able to display an error like this for the password when the user inputs a correct username but incorrect password.

forms.py

from django import forms
from django.contrib.auth.hashers import make_password, check_password
from django.contrib.auth.forms import AuthenticationForm
from .models import User

class LoginForm(AuthenticationForm):
    username = forms.CharField(max_length=255, widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder':  'Username', 'required': True}))

    password = forms.CharField(max_length=255, widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': 'Password', 'required': True}))

    def clean_username(self):
        username = self.cleaned_data['username']

        user = User.objects.filter(username=username)

        if not user:
            raise forms.ValidationError('Incorrect username')

        return username

    def clean_password(self):
        # This is the part I need help with

        # NOTE This code does nothing, just used to
        # display the functionality I want to implement

        password = self.cleaned_data['password']

        if not check_password(password):
            raise forms.ValidationError('Incorrect password')

        return password

views.py

from django.contrib.auth.views import LoginView
from .forms import LoginForm

class LoginUserView(LoginView):
    template_name = 'login.html'
    authentication_form = LoginForm

login.html

{% extends 'base.html' %}

{% block title%}
    Login
{% endblock title %}

{% block content %}
    </div>
    <form method="post">
        {% csrf_token %}
        <div class="mb-4">
            <p class="text-danger">
                {{ form.username.errors.as_text }}
            </p>
            <label for="{{ form.username.label }}" class="form-label">
                {{ form.username.label }}
            </label>
            {{ form.username }}
        </div>
        <div class="mb-4">
            <p class="text-danger">
                {{ form.password.errors.as_text }}
            </p>
            <label for="{{ form.password.label }}" class="form-label">
                {{ form.password.label }}
            </label>
            {{ form.password }}
        </div>
        <button class="btn btn-primary" type="submit">
            Login
        </button>
    </form>
{% endblock content %}

I have tried many different ways to get this to work but just can't figure it out for some reason, I have wrestled with it for about 2 hours now reading through the documentation and over sites, but to no avail. Any help is appreciated.

You can use django's check_password function to do this.

Example -

def clean_password(self):
    user = User.objects.filter(username=username)
    success = user.check_password(password)
    if not success:
        raise forms.ValidationError('Incorrect password')

    return password
Back to Top