Implementing Forgot Password in Django cover image

Implementing Forgot Password in Django

• July 6, 2025

python django

One essential feature in web development that many beginners and intermediates overlook is implementing a forgot password feature, A way to retrieve a lost password. Most web applications will not be considered production-ready without this feature. In this article, I will show you an easy way to implement this feature in a Django application.

Now, Django's auth module comes bundled with views that enable this process. To implement, import the views into your URLs and change the default template. Each view handles a specific function in the forgot password process. These are the views:

  1. django.contrib.auth.views.PasswordResetView
  2. django.contrib.auth.views.PasswordResetDoneView
  3. django.contrib.auth.views.PasswordResetConfirmView
  4. django.contrib.auth.views.PasswordResetCompleteView

The PasswordResetView operates by sending an email to the user. The PasswordResetDoneView is a feedback page for the PasswordResetView. The PasswordResetConfirmView operates by resetting the password. The PasswordResetCompleteView is a feedback page for the PasswordResetConfirmView.

In your urls.py import all the views.

from django.urls import path
from django.contrib.auth.views import PasswordResetView, PasswordResetConfirmView, PasswordResetDoneView, PasswordResetCompleteView

urlpatterns = [

    path('password-reset/', PasswordResetView.as_view(template_name='users/password_reset.html'), name="password_reset"),
    path('password-reset-done/', PasswordResetDoneView.as_view(template_name='users/password_reset_done.html'), name="password_reset_done"),
    path('password-reset-confirm/<uidb64>/<token>', PasswordResetConfirmView.as_view(template_name='users/password_reset_confirm.html'), name="password_reset_confirm"),
    path('password-reset-complete/', PasswordResetCompleteView.as_view(template_name='users/password_reset_complete.html'), name="password_reset_complete"),
]

You will have to change the default template and customise it to fit your application's styling. This is the custom template for my application using Bootstrap 5 and django-crispy-forms.

PasswordResetView

{% extends 'layout.html' %} {% load crispy_forms_tags %}

<!-- Content -->
{% block content %}
<div class="container py-5">
    <div class="col-md-6 offset-md-3">
        <h1 class="display-6 fw-semibold mb-4">Password Reset</h1>
        <p>
            Forgotten your password? Enter your email address below, and we’ll
            email instructions for setting a new one.
        </p>
        <form action="" method="post">
            {% csrf_token %} {{ form|crispy }}
            <button type="submit" class="btn btn-primary">
                Reset Password
            </button>
        </form>
    </div>
</div>
{% endblock content %}

PasswordResetDoneView

{% extends 'layout.html' %}

<!-- Content -->
{% block content %}
<div class="container py-5">
    <div class="col-md-6 offset-md-3">
        <h1 class="display-6 fw-semibold mb-4">Password Reset Sent</h1>
        <p>
            We’ve emailed you instructions for setting your password, if an
            account exists with the email you entered. You should receive them
            shortly.
        </p>
        <p>
            If you don’t receive an email, please make sure you’ve entered the
            address you registered with, and check your spam folder.
        </p>
    </div>
</div>
{% endblock content %}

PasswordResetConfirmView

{% extends 'layout.html' %} {% load crispy_forms_tags %}

<!-- Content -->
{% block content %}
<div class="container py-5">
    <div class="col-md-6 offset-md-3">
        <h1 class="display-6 fw-semibold mb-4">Enter New Password</h1>
        <p>
            Please enter your new password twice so we can verify you typed it
            in correctly.
        </p>
        <form action="" method="post">
            {% csrf_token %} {{ form|crispy }}
            <button type="submit" class="btn btn-primary">
                Change Password
            </button>
        </form>
    </div>
</div>
{% endblock content %}

PasswordResetCompleteView

{% extends 'layout.html' %}

<!-- Content -->
{% block content %}
<div class="container py-5">
    <div class="col-md-6 offset-md-3">
        <h1 class="display-6 fw-semibold mb-4">Password Reset Complete</h1>
        <p>Your password has been set. You may go ahead and log in now.</p>
        <p>
            <a href="{% url 'login' %}">Sign In</a>
        </p>
    </div>
</div>
{% endblock content %}

With the above code, you have successfully implemented a forgot password feature in your Django application. I am sure you were not expecting it to be that easy, right?