Django password_change() View

Django provides the following two views functions which help us to change passwords.

View Function Description
password_change() It displays a password change form, which allows the user to change their password by retyping the existing password.
password_change_done() It displays a success message when a user successfully updates the password.

Both of these views are password protected using login_required decorator. So, if you try to access these views without logging in, Django will redirect you to the URL specified in LOGIN_URL setting, which in our case happens to be /cadmin/login/. If we had not set LOGIN_URL to 'login' then login_required would have redirected us to default login URL which is /accounts/login/. We can verify this by adding the following URL pattern at the beginning of the urlpatterns list in cadmin's urls.py.

TGDB/django_project/cadmin/urls.py

#...
urlpatterns = [
    url(r'^password-change/$', auth_views.password_change , name='password_change'),
    url(r'^$', views.home, name='home'),
    #...
]

If you are already logged in, logout first and then, visit http://127.0.0.1:8000/cadmin/password-change/, you will be redirected to http://127.0.0.1:8000/cadmin/login/?next=/cadmin/password-change/.

password_change-view-is-protected.png

Notice that the redirected URL contains next query parameter whose value is /cadmin/password-change/. It means that after successful login the django.contrib.auth.login() view function will redirect the user to /cadmin/password-change/.

The password_change() view works in conjunction with password_change_done() view. The job of the password_change_done() view is to display the success message when user successfully updates password. The password_change() view accepts an additional argument named post_change_redirect. The post_change_redirect points to the URL to redirect after successful password change. Generally, it points to the URL pattern which calls password_change_done() view.

Open cadmin's urls.py and add another URL pattern named password_change_done and update password_change URL pattern as follows:

TGDB/django_project/cadmin/urls.py

#...
urlpatterns = [
    url(r'^password-change-done/$',
        auth_views.password_change_done,
        name='password_change_done'
    ),
    url(r'^password-change/$',
        auth_views.password_change,
        {'post_change_redirect': 'password_change_done'},
        name='password_change'
    ),
    url(r'^$', views.home, name='home'),
    #...
]

To view the fruits of our labor visit http://127.0.0.1:8000/cadmin/password-change/. If you are not already logged in, login now and you will be presented with password change page, which looks like this:

password_change-page.png

To change the password, enter your old password then your new password twice and hit "CHANGE MY PASSWORD" button at the bottom of the screen. On success you will be redirected to http://127.0.0.1:8000/cadmin/password-change-done/, which looks like this:

password_change_done-page.png

By default, password_change() and password_change_done() uses password_change_form.html and password_change_done.html templates respectively from Django Admin app (django.contrib.admin). We can override this behavior by using template_name keyword argument as usual.

Update password_change and password_change_done URL patterns as follows:

TGDB/django_project/cadmin/urls.py

#...
urlpatterns = [
    url(r'^password-change-done/$',
        auth_views.password_change_done,
        {'template_name': 'cadmin/password_change_done.html'},
        name='password_change_done'
    ),
    url(r'^password-change/$',
        auth_views.password_change,
        {'template_name': 'cadmin/password_change.html' , 'post_change_redirect': 'password_change_done'},
        name='password_change'
    ),
    #...
]

Create two new templates password_change.html and password_change_done.html in the cadmin app with the following code.

TGDB/django_project/cadmin/templates/cadmin/password_change.html

{% extends "cadmin/base_admin.html" %}

{% block title %}
    Password Change - {{ block.super }}
{% endblock %}

{% block main %}

    <div class="main">

            <p>&#187; <a href="{% url 'password_change' %}">Change Password</a> </p>

            <h3>Change Password</h3>

            <form action="{% url 'password_change' %}" method="post">
                {% csrf_token %}
                <table>
                    {{ form.as_table }}
                    <tr>
                        <td></td>
                        <td><input type="submit" value="Submit"></td>
                    </tr>
                </table>
            </form>
    </div>

{% endblock %}

TGDB/django_project/cadmin/templates/cadmin/password_change_done.html

{% extends "cadmin/base_admin.html" %}

{% block title %}
    Password Change - {{ block.super }}
{% endblock %}

{% block main %}

    <div class="main">

            <p>Password Changed</p>
    </div>

{% endblock %}

Visit the http://127.0.0.1:8000/cadmin/password-change/ and you should see our custom password change template instead of the default one.

custom-password-change-template.png

Update the password of the logged in user and on success you will get a page like this:

custom-password-change-done-template.png