Implement Change and Forgot Password Functionality in Django

User authentication is a critical aspect of web applications, and ensuring the security of user accounts is paramount. In this tutorial, we’ll explore how to implement password change and password reset (forgot password) functionality in a Django application. These features allow users to update their passwords and recover their accounts in case they forget their passwords.

Prerequisites

Before we proceed, ensure that you have a Django project with user authentication set up. If not, you can follow the steps in the previous tutorial on creating signup, login, and logout functionality in Django.

Password Update Change Functionality

Lets create view, templates and urls for Password Update

Step 1: Create a Password Change View

In your app’s views.py file, create a view for password change:

from django.contrib.auth.forms import PasswordChangeForm
from django.contrib.auth import update_session_auth_hash
from django.shortcuts import render, redirect

def change_password(request):
    if request.method == 'POST':
        form = PasswordChangeForm(request.user, request.POST)
        if form.is_valid():
            user = form.save()
            update_session_auth_hash(request, user)  # To keep the user logged in
            return redirect('password_change_done')
    else:
        form = PasswordChangeForm(request.user)
    return render(request, 'change-password/change_password.html', {'form': form})

def password_change_done(request):
    return render(request, 'change-password/password_change_done.html')

Step 2: Create a Password Change Template

Create a folder named change-password in your app’s templates directory. Inside this folder, create a file named change-password/change_password.html. This is where you can customize your password change form:

{% extends "base.html" %}

{% block title %}Change Password{% endblock %}

{% block content %}
  <h2>Change Password</h2>
  <form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Change Password</button>
  </form>
{% endblock %}

Step 3: Define URL for Password Change

In your app’s urls.py file, define the URL for the password change view:

from django.urls import path
from . import views

urlpatterns = [
    # ... (other URLs)
    path('change_password/', views.change_password, name='change_password'),
    path('password_change_done/', views.password_change_done, name='password_change_done'),
]

Step 4: Create a Password Change Done Template (Optional)

Optionally, you can create a template for the password change success page: change-password/change_password.html

{% extends "base.html" %}

{% block title %}Password Changed{% endblock %}

{% block content %}
  <h2>Password Changed</h2>
  <p>Your password has been successfully changed.</p>
{% endblock %}

Forgot Password (Password Reset) Functionality

Lets create view, templates and Urls for Password Forgot

Step 1: Create a Password Reset View

Django provides built-in views and templates for password reset functionality, so you don’t need to create a custom view for this. However, you should set up the necessary templates.

Step 2: Create Password Reset Templates (Optional)

You can customize the password reset templates if needed. Create the following templates in your app’s templates/password-reset directory:

  • password_reset_form.html: Customize the password reset form.
{% extends "base.html" %}

{% block title %}Password Reset{% endblock %}

{% block content %}
  <h2>Password Reset</h2>
  <p>Enter your email address to reset your password.</p>
  <form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Reset Password</button>
  </form>
{% endblock %}
  • password_reset_subject.txt: Customize the subject of the password reset email.
Password Reset for Your Website
  • password_reset_email.html: Customize the content of the password reset email.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Password Reset</title>
</head>
<body>
    <p>Click the following link to reset your password:</p>
    <p><a href="http://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}">Reset Password</a></p>
    <p>If you didn't request a password reset, please ignore this email.</p>
</body>
</html>
  • password_reset_done.html: Customize the confirmation page after a password reset email is sent.
{% extends "base.html" %}

{% block title %}Password Reset Email Sent{% endblock %}

{% block content %}
  <h2>Password Reset Email Sent</h2>
  <p>We've sent you an email with instructions on how to reset your password. Please check your inbox.</p>
{% endblock %}
  • password_reset_confirm.html: Customize the password reset confirmation page.
{% extends "base.html" %}

{% block title %}Reset Password{% endblock %}

{% block content %}
  <h2>Reset Password</h2>
  <p>Enter your new password below:</p>
  <form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Reset Password</button>
  </form>
{% endblock %}

You can find the default templates in Django’s source code and modify them according to your project’s design.

Step 3: Define URLs for Password Reset

In your app’s urls.py file, include the built-in password reset URLs

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

urlpatterns = [
    # ... (other URLs)
    path('password_reset/', auth_views.PasswordResetView.as_view(
        template_name='password-reset/password_reset_form.html',
        email_template_name='password-reset/password_reset_email.html',
        subject_template_name='password-reset/password_reset_subject.txt',
        success_url='/password_reset_done/'
    ), name='password_reset'),
    path('password_reset_done/', auth_views.PasswordResetDoneView.as_view(
        template_name='password-reset/password_reset_done.html'
    ), name='password_reset_done'),
    path('reset/<uidb64>/<token>/', auth_views.PasswordResetConfirmView.as_view(
        template_name='password-reset/password_reset_confirm.html',
        success_url='/password_reset_complete/'
    ), name='password_reset_confirm'),
    path('password_reset_complete/', auth_views.PasswordResetCompleteView.as_view(
        template_name='password-reset/password_reset_complete.html'
    ), name='password_reset_complete'),
]

Step 3: Configure Email Settings

As we are going to send email on for reset password, we need to setup configuration in settings.py. Open your project’s settings.py file and configure your email settings. For this example, we will use Gmail’s SMTP server for sending emails:

# settings.py

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = '[email protected]'
EMAIL_HOST_PASSWORD = 'your_email_password'

Replace [email protected] and your_email_password with your Gmail email and password.

Please watch this video, to send email using Gmail.

Note that using your actual email and password directly in your code is not recommended for production. Instead, consider using environment variables or other secure methods to store these credentials. Read more on How to Protect Sensitive Data in Python Projects like Django and Flask

Finalizing Setup and Run Server

Here is the updated base.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{% block title %}Your Website Title{% endblock %}</title>
    <!-- Add your CSS and JavaScript links here -->
</head>

<body>
    <header>
        {% if user.is_authenticated %}
        <p>Hello, {{ user.username }}! | <a href="{% url 'change_password' %}">Change Password</a> | <a href="{% url 'logout' %}">Logout</a></p>
        {% else %}
        <p><a href="{% url 'login' %}">Login</a> | <a href="{% url 'signup' %}">Sign up</a> | <a href="{% url 'password_reset' %}">Reset Password</a></p>
        {% endif %}
    </header>

    <main>
        {% block content %}
        {% endblock %}
    </main>

    <footer>
        <!-- Add your footer content here -->
    </footer>
</body>

</html>

Finally, start the development server:

python manage.py runserver

You can now access your application at http://localhost:8000/ and navigate to the registration page to sign up, and subsequently, you can add login and logout functionality as needed.

Conslusion

With these steps, you’ve implemented password change and password reset (forgot password) functionality in your Django application. Users can now update their passwords and recover their accounts if they forget their passwords. Customization options are available for the templates and views to match your project’s requirements and design.

Find this project on Github.

Blogs You Might Like to Read!