Django comes with support for MIDDLEWARE and provides several useful ones by default. I usually try to make my projects as useable as possible, and some debug middleware is only useful when development.
Example Middleware
Since the order and layering often matter, I’ll usually configure all my optional middleware in the correct spot like bellow, with a short comment.
MIDDLEWARE = [
"debug_toolbar.middleware.DebugToolbarMiddleware", # Only enabled for debug
"django.middleware.security.SecurityMiddleware",
"whitenoise.middleware.WhiteNoiseMiddleware", # Used primarily for docker
"django.middleware.locale.LocaleMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
Then I’ll use other conditional checks to see if this list (or other variables) need to be modified.
Django Debug Toolbar
Even though it makes some requests slower (so you’re unlikely to want to enable it in production), django-debug-toolbar
is a very useful tool for debugging while developing.
Usually I will do an import check and then take advantage of ImportError
if I don’t have it installed.
# in <project>/settings.py
try:
# Check to see if it is installed
import debug_toolbar
except ImportError:
# If not installed, we'll remove it from our settings
INSTALLED_APPS.remove("debug_toolbar")
MIDDLEWARE.remove("debug_toolbar.middleware.DebugToolbarMiddleware")
# in <project>/urls.py
# We do the same import check and append it to the end of our URL patterns
# if we succeed at the import.
try:
import debug_toolbar
except ImportError:
pass
else:
urlpatterns.append(path("__debug__/", include(debug_toolbar.urls)))
Whitenoise
Lately, most of my Django projects ultimately get deployed via docker containers, so I will use whitenoise to help with static files.
try:
# Check to see if whitenoise is enabled
import whitenoise.middleware
except ImportError:
# if it's not enabled, we can remove the middleware setting, and use basic
# file storage settings
MIDDLEWARE.remove("whitenoise.middleware.WhiteNoiseMiddleware")
STATICFILES_STORAGE = "django.contrib.staticfiles.storage.ManifestStaticFilesStorage"
else:
# Otherwise we want to use the whitenoise version of the above storage settings
STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"
Conclusion
Since Exceptions are generally easy to handle in Python, I will often use this pattern of catching ImportError
for many types of optional code.