how can i display error messages when using the inbuilt reset password and password change in Django

Question:

I am working on some user forgot password as well as password reset using Django Built in functionality but I am making use of my template to render the page and form. I will like a way to render the messages either error or success messages so that the user understands what is going on in case the password is too short or so.

urls.py

from django.urls import path
from . import views
from django.contrib.auth import views as auth_views

urlpatterns = [
    path('', views.Dashboard, name='dashboard'),
    path('login/', views.Login, name='login'),
    path('logout/', views.Logout, name='logout'),
    path('register/', views.Register, name='register'),
    path('forgetpassword/', views.ForgetPassword, name='forgetpassword'),
    path('password_change/', auth_views.PasswordChangeView.as_view(
        template_name='auth/password/change-password.html'), name='password_change'),
    path('password_change/done/', auth_views.PasswordChangeDoneView.as_view(
        template_name='auth/password/change-password-done.html'), name='password_change_done'),

change-password.html

{% extends 'auth/base.html' %}
{% load static %}
{% block content %}
<div class="page-wrapper" style="height: 100vh!important;">
    <div class="page-content--bge5">
        <div class="container">
            <div class="login-wrap">
                <div class="login-content">
                    <div class="login-logo">
                        <a href="#">
                            <img src="{% static 'images/icon/logo-new.png' %}" alt="CoolAdmin">
                        </a>
                    </div>
                    {% if messages %}
                    {% for message in messages %}
                    <div class="alert alert-{{message.tags}} with-close alert-dismissible fade show">
                        {{message}}
                        <button type="button" class="close" data-dismiss="alert" aria-label="Close">
                            <span aria-hidden="true">&times;</span>
                        </button>
                    </div>
                    {% endfor %}
                    {% endif %}
                    <div class="login-form">
                        <form method="POST">
                            {% csrf_token %}
                            <div class="form-group">
                                <label>Current Password</label>
                                <input class="au-input au-input--full" type="password" name="old_password" id="id_old_password" placeholder="Current Password" required>
                            </div>
                            <div class="form-group">
                                <label>New Password</label>
                                <input class="au-input au-input--full" type="password" name="new_password1" id="id_new_password1" placeholder="New Password" required>
                            </div>
                            <div class="form-group">
                                <label>New Password</label>
                                <input class="au-input au-input--full" type="password" name="new_password2" id="id_new_password2" placeholder="New Password" required>
                            </div>
                            <button class="au-btn au-btn--block au-btn--green m-b-20" type="submit">Change Password</button>
                        </form>
                    </div>
                </div>
            </div>
        </div>
    </div>

</div>
{% endblock %}
Asked By: coderboy

||

Answers:

The form already has the errors in it’s instance. For some reason people use the message framework for showing errors which is in fact more difficult than simply using the form in the template. The view passes the form instance to your template so you can use it to render the form and render it’s errors. Try this in your template:

To render non-field errors:

{% for error in form.non_field_errors %}
    {{ error }}
{% endfor %}

To render field errors use form.field_name.errors:

{% for error in form.new_password1.errors %}
    {{ error }}
{% endfor %}

As a note Rendering the form manually (by writing the tags yourself <input ....>) increases the difficulty of making forms for no good reason. Perhaps one might not like using the default rendered forms but there are ways to customize that in the form’s class or using some package. See django-widget-tweaks and django-crispy-forms two great packages to customize form rendering.

Answered By: Abdul Aziz Barkat

I was able to solve the problem by following the previous answer. I added the error tags in the HTML which made it work perfectly and displayed the error nicely using some styles.

{% for error in form.old_password.errors %}
    <div class="alert alert-danger with-close alert-dismissible fade show">
        {{error}}
        <button type="button" class="close" data-dismiss="alert" aria-label="Close">
            <span aria-hidden="true">&times;</span>
        </button>
    </div>
{% endfor %}

{% for error in form.new_password1.errors %}
    <div class="alert alert-danger with-close alert-dismissible fade show">
        {{error}}
        <button type="button" class="close" data-dismiss="alert" aria-label="Close">
            <span aria-hidden="true">&times;</span>
        </button>
    </div>
{% endfor %}

{% for error in form.new_password2.errors %}
    <div class="alert alert-danger with-close alert-dismissible fade show">
        {{error}}
        <button type="button" class="close" data-dismiss="alert" aria-label="Close">
            <span aria-hidden="true">&times;</span>
        </button>
    </div>
{% endfor %}

<div class="login-form">
    <form method="POST">
        {% csrf_token %}
        <div class="form-group">
            <label>Current Password</label>
            <input class="au-input au-input--full" type="password" name="old_password" id="id_old_password" placeholder="Current Password" required>
        </div>
        <div class="form-group">
            <label>New Password</label>
            <input class="au-input au-input--full" type="password" name="new_password1" id="id_new_password1" placeholder="New Password" required>
        </div>
        <div class="form-group">
            <label>New Password</label>
            <input class="au-input au-input--full" type="password" name="new_password2" id="id_new_password2" placeholder="New Password" required>
        </div>
        <button class="au-btn au-btn--block au-btn--green m-b-20" type="submit">Change Password</button>
    </form>
</div>
Answered By: coderboy

I put an increment with {% if %}, to appear only when there is an error.

{% if form.new_password1.errors %}
  {% for error in form.new_password1.errors %}
    <div class="alert alert-danger with-close alert-dismissible fade show">
      {{error}}
    </div>
  {% endfor %}
{% endif %}

{% if form.new_password2.errors %}
  {% for error in form.new_password2.errors %}
    <div class="alert alert-danger with-close alert-dismissible fade show">
      {{error}}
    </div>
  {% endfor %}
{% endif %}
Answered By: Brunomcr