Django password_change() View

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

View Function Description
password_change() It displays a password change form, which allows user to change their password by retyping 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 view without logging in, Django will redirect you to URL specified in LOGIN_URL, which in our case happens to be http://127.0.0.1:2000/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/. To show you what I mean, open cadmin app's urls.py and add the following code url pattern at the beginning of the urlpatterns list.

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

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

Notice that the above URL also contains next GET parameter, which makes the built-in login() view to redirect the user to /cadmin/password-change/ after successful login.

The password_change() view works in conjuction with password_change_done() view. The job of the password_change_done() view is to display 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 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:

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'
    ),

    ...
]

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

[img]

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

[img]

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

Update password_change and password_change_done urls as follows:

urlpatterns = [

    url(r'^accounts/password-change-done/$',
        auth_views.password_change_done,
        {'template_name': 'cadmin/password_change_done.html'},
        name='password_change_done'
    ),

    url(r'^accounts/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 content.

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 %}

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 template instead of the default one.

[img]