Customizing Error Page Handling in Django 3.1

Anthony Dattolo
2 min readDec 27, 2020

The fastest way to implement custom error pages, like 404 and 500, in a Django 3.1 project.

We’ll use an app_name of appName for our purposes, and assume default configurations.

Project settings.py

The simplest way to customize error handling, is to add <errorType>.html files to our APP template root directory. NOT the sub-directory that contains the app-specific templates, but its parent.

By default, and for convenience, Django will automatically look here for certain default method error handling views. They are as follows:

  • 404, page_not_found(): projectName/appName/templates/404.html
  • 500, server_error(): projectName/appName/templates/500.html
  • 403, permission_denied(): projectName/appName/templates/403.html
  • 400, bad_request(): projectName/appName/templates/400.html

*note: unless you change it, your app-specific templates still belong in projectName/appName/templates/appName/

projectName/settings.py

We now need to let Django know we want to look for these default error template overrides, by adding the app level template root directory to the project level settings.py. While we’re here, we also need to set debug mode to false, and set the allowed hosts — we’ll use “*” for now.

#Default base directory
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
#App level directory ADD THIS
APPNAME_DIR = os.path.join(BASE_DIR, ‘templates’)
...
DEBUG = FalseALLOWED_HOSTS = ["*"]...TEMPLATES = [{'BACKEND': 'django.template.backends.django.DjangoTemplates','DIRS': [# Add APPNAME_DIR variable to set project template directory for custom# error page handling. eg, 404.html in project template root dirAPPNAME_DIR],'APP_DIRS': True,'OPTIONS': {'context_processors': ['django.template.context_processors.debug','django.template.context_processors.request','django.contrib.auth.context_processors.auth','django.contrib.messages.context_processors.messages',],},},]

Custom 404 template

Using the 404 error as an example, let’s edit the 404.html located in our app template root directory. Assume we have a DetailView in our urls.py that allows us to take in a custom string parameter to pass to the detail, and then we use a get_object_or_404() method to access it, and it throws the 404 error because we misspell the URL name.

urlpatterns = [
path(‘appname/<str:customParameterName>/’, AppNameDetailView.as_view(), name=”appname-detail”)
]

The .page_not_found() or default 404 error method, gives us access to a template variable which can be referred to as either request_path or request.path. This will give you the full relative directory path as a string, and so just to demonstrate if you only want to return the misspelled term, we’ll use the builtin template method slice.

<!-- template code: 404.html -->{% extends "appname/layout.html" %}{% block title %}Page Not Found!{% endblock %}{% block body %}<b>{{ request.path|slice:"9:-1" }} does not exist yet!</b><br><a href="{% url 'appname:appname-create' %}">Create New Page</a>{% endblock %}

That’s it, if you misspell a URL for a DetailView, it’ll now show the template you defined, and display the misspelled term.

--

--

Anthony Dattolo

CS at IU, Software Engineer, I nerd out about startups, strategy, finance, and marketplaces