
Implementing Forgot Password in Django
• July 6, 2025
python djangoOne 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:
django.contrib.auth.views.PasswordResetView
django.contrib.auth.views.PasswordResetDoneView
django.contrib.auth.views.PasswordResetConfirmView
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?