After doing a couple of of searches, I came across a few, older (2010/2011) middleware packages that looked like good solutions. Since the packages were older, and I have never written any custom middleware before for Django, I decided to write my own solution. I was really surprised at how easy it was to plug in some custom middleware.
Here's how I created my own middleware to require login for every view within my project.
Create a "middleware.py" for your project
Create your custom Middleware Component
Per Django's documentation: Each middleware component is a single Python class. So, creating your own middleware component looks like this:
class MyMiddlewareClass(Object): # define custom methods in here
For my purposes, I created the following class:
class LoginRequiredMiddleware(Object): # my custom methods in here
Build out your custom Middleware Methods
from django.http import HttpResponseForbidden class LoginRequiredMiddleware(object): def process_view(self, request, view_func, view_args, view_kwargs): if request.user.is_authenticated(): return None else: return HttpResponseForbidden()
This is a very basic implementation of the functionality I needed. Before Django calls the view (view_func), this method simply checks if the request is authenticated or not.
If it is, it returns None, which tells Django to continue on processing the request as per usual, eventually executing view_func. If it isn't, it returns the convenient HttpResponseForbidden.
I defined the process_view method as opposed to process_request method because I wanted Django to catch 404 errors before running my custom middleware. Otherwise, my middleware would send an unauthenticated user to the login page even when they requested a URL that hasn't been defined in my URL patterns.
Obviously this is too basic. What about the STATIC_URL and MEDIA_URL? Or the Django Admin, or any other pages you want to be public?
To handle these contingencies, I built out the method a bit more to look like this:
import re from django.http import HttpResponseRedirect from django.conf import settings class LoginRequiredMiddleware(object): PUBLIC_URL_PATTERNS = [ r'^%s.*$' % settings.STATIC_URL, r'^%s.*$' % settings.MEDIA_URL, r'^/admin/.*$', r'^/(\?.*)?$', r'^%s.*$' % settings.LOGIN_URL, ] PUBLIC_URL_PATTERNS = [re.compile(exp) for exp in PUBLIC_URL_PATTERNS] def process_view(self, request, view_func, view_args, view_kwargs): path = request.path if any(pattern.match(path) for pattern in self.PUBLIC_URL_PATTERNS): return None elif request.user.is_authenticated(): return None else: redirecturl = settings.LOGIN_URL + "?go=" + path return HttpResponseRedirect(redirecturl)
The method now checks to see if the requested URL matches any public URL defined in PUBLIC_URL_PATTERNS. It also appends a query string to the LOGIN_URL that the user is re-directed to. So that we can easily send the user to the URL they requested after he/she logs in.
This is still pretty basic. And it only accounts for a few public URL patterns. It'll need to be built out a bit to be more robust. And I might follow up with another post once I do that. I wouldn't recommended blindly copying this code for use in your own project.
Add your custom Middleware to your settings
MIDDLEWARE_CLASSES = ( ..., 'projectroot.middleware.LoginRequiredMiddleware', )
Be sure to replace projectroot with the module name of your project configuration folder. My full path, for example, is "dylansproject.middleware.LoginRequiredMiddleware". Now your project is all set up to use your custom middleware!