[Fixed]-Python/Django: How to display error messages on invalid login?


in your template

{% for message in messages %}
    <div class="alert alert-success">
        <a class="close" href="#" data-dismiss="alert">Γ—</a>
           {{ message }}

{% endfor %}

in view

from django.contrib import messages

def login(request):
    if request.method == 'POST':
        form = AuthenticationForm(request.POST)
        username = request.POST['username']
        password = request.POST['password']
        user = authenticate(username=username, password=password)
        if user is not None:
            if user.is_active:
                auth_login(request, user)
                return redirect('index')
            messages.error(request,'username or password not correct')
            return redirect('login')
        form = AuthenticationForm()
    return render(request, 'todo/login.html', {'form': form})


You should just add inside your template:

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

{% block content %}

{% if form.errors %}
    <p>username or password not correct</p>
{% endif %}

<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Login</button>
{% endblock %}


Updating for Django 2.0:

For individual field errors (e.g) :

    <input type="text" class="form-control my-4" id="id_username" placeholder="Username" name="username">

    {% for error in form.username.errors %}
         <p class="text-danger">{{ error }}</p>
    {% endfor %}

For non field errors (e.g if password is incorrect):

     {% if form.non_field_errors %}
            {% for error in form.non_field_errors %}
                <p class="text-danger">{{ error }}</p>
            {% endfor %}
      {% endif %}

You should place the above at the end of all fields.


You already have {{ form.as_p }} in your template, so Django will show any form errors.

The problem is that the AuthenticationForm takes request as its first argument. You can then use form.is_valid() to check whether the username and password are valid and that the user is active, instead of fetching the data from request.POST manually.

def login(request):
    if request.method == 'POST':
        form = AuthenticationForm(request, request.POST)
        if form.is_valid():
            auth_login(self.request, form.get_user())
            return redirect('index')
        form = AuthenticationForm(request)
    return render(request, 'todo/login.html', {'form': form})

Another option would be to use the built-in LoginView instead of writing your own:

from django.contrib.auth import views as auth_views

urlpatterns = [
    path('accounts/login/', auth_views.LoginView.as_view(template_name='todo/login.html')),

Then set LOGIN_REDIRECT_URL in your settings.


Leave a comment