You want to add, remove or update content from requests or responses before or after they cross into view methods or templates.
Create a Python class with the various methods supported by Django middleware:
process_template_response(). Define the Python class as part of the
MIDDLEWARE_CLASSES variable in your Django project's
In most circumstances you add, remove or update content from requests or responses directly in Django view methods. However, sometimes it's convenient to apply such modifications across all requests and responses, in which case you benefit greatly from using Django middleware.
Django middleware is composed as Python classes. You can think of Django middleware as Python classes that are executed on all requests and responses that occur in an application. However, before exploring the structure required for these Django middleware Python classes, we'll take a brief detour to look at Django's built-in middleware classes to know what's already available and get a better understanding of how Django middleware works.
Django comes equipped with a series of middleware classes, some of which are enabled by default on all Django projects. If you open a Django project's
settings.py file you'll notice the
MIDDLEWARE_CLASSES variable. The
MIDDLEWARE_CLASSES variable is assigned a tuple of Python classes that operate as Django middleware. Listing 1 illustrates the default contents of the
As you can see in listing 1, Django in its out-of-the-box state already comes enabled with seven middleware classes, so all requests and responses are already running through these seven classes. If you plan to leverage Django's main features, I would advise you not to remove any of these default middleware classes. However, you could leave the
MIDDLEWARE_CLASSES variable empty if you wish, just be aware you may break certain Django functionalities in the process.
To give you a better understanding of what the Django middleware classes in listing 1 do and help you make a more informed decision to disable them or not, table 1 describes the functionality for each of these middleware classes.
|Provides several security enhancements to the request/response cycle.|
|Enables session support.|
|Provides a common set of features, that include:|
|Adds protection against Cross Site Request Forgeries by adding hidden form fields to POST forms and checking requests for the correct value.|
|Adds the user attribute, representing the currently-logged-in user, to every incoming HttpRequest object. NOTE: This middleware class depends on functionality from the middleware |
|Enables cookie-based and session-based message support. NOTE: This middleware class depends on functionality from the middleware |
|Provides clickjacking protection via the X-Frame-Options header. For more details on what is clickjacking see: http://en.wikipedia.org/wiki/Clickjacking.|
As you can see in table 1, although the purpose of the various default middleware classes varies considerably, their functionality applies to features that need to be applied across all requests and responses. Another important factor of the middleware classes in table 1 is that some are dependent on others. For example, the
AuthenticationMiddleware class is designed on the assumption it will have access to functionality provided by the
SessionMiddleware class. Such dependencies are important because it makes the class definition order relevant (i.e. certain middleware classes need to be defined before others in
MIDDLEWARE_CLASSES) a topic I'll elaborate on more in the next section.
In addition to the default middleware classes presented in table 1, Django also includes other middleware classes. Table 2 illustrates the remaining set of Django middleware classes you can leverage in your projects, which can be helpful so you don't have to write all your middleware classes.
|Response-phase cache middleware that updates the cache if the response is cacheable.NOTE: |
|Request-phase cache middleware that fetches a page from the cache.NOTE:|
|Sends broken link notification emails to |
|Compresses content for browsers that understand GZip compression, which is all modern browsers. NOTE: |
|Handles conditional GET operations. If the response has an ETag or Last-Modified header, and the request has If-None-Match or If-Modified-Since, the response is replaced by an HttpNotModified.|
|Parses a request and decides what translation object to install in the current thread context. This allows pages to be dynamically translated to the language the user desires.|
|Adds the |
|Allows web-server-provided authentication.If request.user is not authenticated, this middleware attempts to authenticate the username passed in the |
|Each time a Django application raises a 404 error, this middleware checks the flatpages database for the requested URL as a last resort.|
|Each time a Django application raises a 404 error, this middleware checks the redirects database for the requested URL as a last resort.|
Now that you know about Django's built-in middleware classes and what it's they are generally used for, lets take a look at the structure of these middleware classes as well as their execution process.
A Django middleware class can have five callback methods that execute at different points of the request/response life-cycle. Two of these callback methods run in the request phase, while the other three callback methods run in the response phase. The following list provides a brief description of these methods:
__init__(Class initialization phase).- This method is part of all Python classes and is not specific to Django middleware. It gets called only once, when the Web server responds to the first request.
process_request()(request phase).- This method is called on each request, before Django decides which view to execute.
process_view()(request phase).- This method is called on each request, just before Django calls the view.
process_response()(response phase).- This methods is called on all responses before they're returned to the browser.
process_exception()(response phase).- This method is called when and only if the view raises an exception.
process_template_response()(response phase).- This method is called just after the view has finished executing when and only if the response instance has a render() method, indicating that it's a TemplateResponse or equivalent.
|Request phase executes classes from top to bottom & response phase executes classes from bottom to top.|
Middleware class methods that run in the request phase and response phase have an important execution order that is particularly important if you rely on one middleware class to set up something for another middleware class.
Methods in the request phase (i.e.
Methods in the response phase (i.e.
Visually the execution process for the default Django middleware classes in listing 1 is illustrated in figure 1.
Now that you understand the execution process of Django middleware classes as well as the different methods available in a Django middleware class, lets explore the actual Django middleware class methods in depth.
In this section, I'll split a custom Django middleware class into different pieces so you can get a better understanding of the input and output required for each method.
Listing 2 illustrates the top level class definition --
CoffeehouseMiddleware -- which would need to be declared as part of the
MIDDLEWARE_CLASSES definition, as well as the
__init__ method used to initialize the middleware class.
Listing 3 illustrates the
process_request method which is the first overall method to run in a Django middleware class as part of the request phase.
Listing 4 illustrates the
process_view method which is the second overall method to run in a Django middleware class as part of the request phase.
Listing 5 illustrates the
process_exception method which is the first method of the response phase and runs only if an exception occurs in the underlying view.
Listing 6 illustrates the
process_template_response method which is the second method of the response phase and runs only if the response instance has a render() method, indicating that it's a TemplateResponse or equivalent.
Listing 7 illustrates the
process_response method which is the last overall method to run in a Django middleware class as part of the response phase.