Django: Customize the auth app templates with Tabler.io admin template

Jatin Prajapati
5 min readJan 16, 2020

Recently I started learning Python and the best web framework Django. While studying I thought to create a project in which I should override the out-of-the-box auth app templates with custom UI.

As an another thought, I started writing the steps but now I am turning it into an article so other developers like me can get some help for the same type of development work.

I assume that read of the article has basic knowledge of setting up the Django project. However, here I’m providing basic steps to setup the Django application and how to setup the super user to test the log-in functionality out of the box. I’m not providing the complete code and HTML as snippets in this article but you can use my Github repository for your reference.

So, let’s start. For this article, I used the Tabler admin template which is open source.

Create the new Django project using following command.
django-admin startproject django_tabler

Now run the migrations which are already available when we created the project.
python manage.py migrate

Create a super user, just for testing purpose, using following command. Input the provided information the command ask.
python manage.py createsuperuser

Run the application using following command.
python manage.py runserver

If you see the following page then you have successfully setup the Django application.

Now go to the admin section using http://127.0.0.1:8000/admin to check our super user can log-in to the system or not.

I hope you are able to log into the admin section.

Now, let’s start the real fun.

Create a new app named like ‘accounts’, using the following command.
python manage.py startapp accounts

After creating the app you project should look like in the PyCharm.

Create a new directory named ‘templates’ in to the ‘accounts’ app.

And also create another directory named ‘accounts’ inside the ‘templates’ directory you just created. (See the below image how the project structure will look.)

Now, before moving ahead, let’s add the ‘accounts’ app to the settings.py file so the Django know about this new app.

Open the settings.py and append the ‘accounts’ at the bottom of the INSTALLED_APPS array.

Ok. Now, create a base.html and auth-base.html files inside the ‘templates’ directory. The base.html file is used as the layout or base template file for the pages which are behind the authentication and the auth-base.html file is used as the layout or base template file for the pages which are accessed as an anonymous user.

Find the complete working sample code on Github.

Now create following template files in the templates > accounts folder in the accounts app. See the sample code for the HTML markup I used.

  • login.html (extends the auth-base.html)
  • password_change_done.html (extends the base.html)
  • password_change_form.html (extends the base.html)
  • password_reset_complete.html (extends the auth-base.html)
  • password_reset_confirm.html (extends the auth-base.html)
  • password_reset_done.html (extends the auth-base.html)
  • password_reset_email.html (extends the auth-base.html)
  • password_reset_form.html (extends the auth-base.html)
  • profile.html (extends the base.html)

Now we need to create following new forms which inherit from the django.contrib.auth.forms. The extended forms add the necessary HTML attributes to the form fields so they render properly in-lined with the Tabler.io admin template.

You need to create a forms.py file in the accounts app before extending the forms from django.contrib.auth.forms.

from django import forms
from django.contrib.auth.forms import AuthenticationForm as BaseAuthenticationForm
from django.contrib.auth.forms import PasswordResetForm as BasePasswordResetForm
from django.contrib.auth.forms import SetPasswordForm as BaseSetPasswordForm
from django.contrib.auth.forms import UsernameField
from django.contrib.auth import password_validation
from django.utils.translation import gettext, gettext_lazy as _


class AuthenticationForm(BaseAuthenticationForm):
username = UsernameField(widget=forms.TextInput(attrs={
'autofocus': True,
'class': 'form-control',
'placeholder': _('Enter username')
}))
password = forms.CharField(label=_("Password"), strip=False,
widget=forms.PasswordInput(attrs={
'autocomplete': 'current-password',
'class': 'form-control'
}))


class PasswordResetForm(BasePasswordResetForm):
email = forms.EmailField(
label=_("Email"),
max_length=254,
widget=forms.EmailInput(attrs={'autocomplete': 'email', 'class': 'form-control', 'autofocus': True})
)


class SetPasswordForm(BaseSetPasswordForm):
new_password1 = forms.CharField(
label=_("New password"),
widget=forms.PasswordInput(attrs={'autocomplete': 'off', 'class': 'form-control', 'autofocus': True}),
strip=False,
help_text=password_validation.password_validators_help_text_html(),
)
new_password2 = forms.CharField(
label=_("New password confirmation"),
strip=False,
widget=forms.PasswordInput(attrs={'autocomplete': 'off', 'class': 'form-control'}),
)


class PasswordChangeForm(SetPasswordForm):
old_password = forms.CharField(
label=_("Old password"),
strip=False,
widget=forms.PasswordInput(attrs={'autocomplete': 'current-password', 'autofocus': True, 'class': 'form-control'}),
)

Now create views.py file if it does not exists and create a simple view for profile page.

from django.contrib.auth.decorators import login_required
from django.shortcuts import render
from django.utils.translation import gettext, gettext_lazy as _


@login_required
def profile(request):
return render(request, 'accounts/profile.html', {'title': _('Profile'), 'pretitle': _('Manage your profile')})

Now create a urls.py file and add the following lines:

from django.contrib.auth.views import LogoutView, PasswordChangeView, PasswordChangeDoneView, PasswordResetView, \
PasswordResetDoneView, PasswordResetConfirmView, PasswordResetCompleteView
from django.urls import path
from . import views
from django.contrib.auth import views as auth_views

from .forms import AuthenticationForm, PasswordResetForm, SetPasswordForm, PasswordChangeForm

urlpatterns = [
path('login/', auth_views.LoginView.as_view(form_class=AuthenticationForm, template_name='accounts/login.html'), name='login'),
path('logout/', LogoutView.as_view(), name='logout'),

path('password-change/', PasswordChangeView.as_view(template_name='accounts/password_change_form.html',
form_class=PasswordChangeForm), name='password_change'),
path('password-change/done/', PasswordChangeDoneView.as_view(template_name='accounts/password_change_done.html',), name='password_change_done'),

path('password-reset/', PasswordResetView.as_view(template_name='accounts/password_reset_form.html', form_class=PasswordResetForm,
email_template_name='accounts/password_reset_email.html'), name='password_reset'),
path('password-reset/done/', PasswordResetDoneView.as_view(template_name='accounts/password_reset_done.html'), name='password_reset_done'),
path('reset/<uidb64>/<token>/', PasswordResetConfirmView.as_view(template_name='accounts/password_reset_confirm.html', form_class=SetPasswordForm), name='password_reset_confirm'),
path('reset/done/', PasswordResetCompleteView.as_view(template_name='accounts/password_reset_complete.html'), name='password_reset_complete'),

path('profile/', views.profile, name='profile'),
]

Here in this urls.py file, I’ve created each URL used for login/logout, password reset, password change and profile. All these are custom URL with custom configurations to use our new extended forms.

Now you need to include this urls in to the project’s urls.py file, as shown in the below snippet.

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
path('accounts/', include('accounts.urls')), # URLs from accounts app
path('admin/', admin.site.urls),
]

Now run you app and go to http://127.0.0.1:8000/accounts/login page to see the custom themed login page.

So, this way we can create complete custom auth system with custom HTML admin theme/template.

Happy Python and Django coding!!!!!

--

--