This page looks best with JavaScript enabled

Django add username field to Password Reset page

 ·  ☕ 2 min read  ·  🐨 Puliyo

Introduction

I wanted to add username field to password reset page in Django.

Since Django v2, auth view has migrated to Class View and I weren’t able to find clear instruction online on how to achieve this.

So this page is for you guys having the same intention.

Description of Class View can be found here.

Django Form

Django by default uses PasswordResetForm and it only includes email field in its form.

Full code of PasswordResetForm can be found here.

Inherit this class as below and add the username field.

from django import forms
from django.contrib.auth.forms import PasswordResetForm

class MyPasswordResetForm(PasswordResetForm):
	username = forms.CharField(max_length=254)
	field_order = ['username', 'email']

Very clean :)

When you add extra field like this, it will appear after the fields from PasswordResetForm, ie, after the email field.

Since I want email to come after username, I’ve declared field_order.

Django View

We now inherit the default view class, PasswordResetView, to handle our custom Form.

Full code of PasswordResetView can be found here.

from django.shortcuts import render, redirect
from django.contrib.auth import get_user_model
from django.contrib.auth.views import PasswordResetView
from .forms import MyPasswordResetForm

class MyPasswordResetView(PasswordResetView):
	form_class = MyPasswordResetForm

	def form_valid(self, form):
		username = form.cleaned_data.get('username')
		email = form.cleaned_data.get('email', '').lower()
		try:
			user = get_user_model().objects.get(username=username, email=email)
		except(get_user_model().DoesNotExist):
			user = None
		if user is None:
			return redirect('password_reset_done')
		return super().form_valid(form)

Override the class attribute form_class and tell to use our own View.

Override the form_valid method and add codes to handle username.

Above code will search for user using the username and email, assuming either or both field is unique so multi result does not return.

If user found, continue with the reset process and send email.

If user not found, don’t send email and redirect to ‘password_reset_done’ page (user not found is not reported to user for security).

Django HTML template

Create template for the view. No extra modification here.

I am using default path: templates\registration\password_reset_form.html

<form method="post">
{% csrf_token %}
	{% for field in form %}
	<div>
		{{ field.label_tag }}
		{{ field }}
		{% if field.help_text %}<p>{{ field.help_text }}</p>{% endif %}
		{% for error in field.errors %}<p>* {{ error|escape }}</p>{% endfor %}
	</div>
	{% endfor %}
	<button type="submit">Submit</button>
</form>

Django URL

Last of all, include the view MyPasswordResetView to your urls file.

from django.urls import include, path
from . import views

urlpatterns = [
	path('password_reset/', views.MyPasswordResetView.as_view(), name='password_reset'),
	path('', include('django.contrib.auth.urls')), # first match, first served
]

Result

That’s it! My password reset page now looks like this:

pssswd_reset_page
Share on