1👍
So, where should I set the custom middleware’s path in MIDDLEWARE in settings.py?
It depends on what your middleware needs and what should run before and after that middleware. Indeed, imagine that you want to print the request.user
, so:
def simple_middleware(get_response):
print('Only once the server starts')
def middleware(request):
print(f'Before a view is called {request.user}')
response = get_response(request)
print('After a view is called')
return response
return middleware
While in the views, if you use AuthenticationMiddleware
, there is always a request.user
, if you put this at the top of the MIDDLEWARE
setting, it will not have been set. Indeed, the AuthenticationMiddleware
sets request.user
, so that will need to run first. We thus will have to put our simple_middleware
after the AuthenticationMiddleware
.
For a lot of middleware it might be best to put it at the end of the list, since then you can assume that all builtin middleware will have pre-processed the request, and thus has set the session store and the .user
at the request. Your middleware will also be the first one to exit, so you don’t have to check if a custom error page has been produced for example.
The Django documentation has a section named middleware ordering that briefly explains the most common builtin middleware and how they depend on each other. For example the AuthenticationMiddleware
[Django-doc] depends on the SessionMiddleware
[Django-doc] because details about the logged in user are stored in the session variables, and thus the AuthenticationMiddleware
needs access to session variables to determine what user is attached to the request.
It is true that most Django related packages that provide middleware, often do not document it very properly where to put it. As a general rule of thumb, usually one can use:
MIDDLEWARE = [
# builtin middleware (django.middleware and django.contrib.*.middleware)
# …,
# django packages used
# …,
# your own custom middleware
# …
]
of course there can be exceptions. Imagine that you design your own session variable mechanism, then you can replace Django’s builtin with yours, and that will have to run before the AuthenticationMiddleware
, for reasons discussed earlier. Ofthen the exact order does not matter much, as long as the constraints are satisfied mentioned in the documentation, and if you built on top of the middleware (like the example with request.user
), that you ensure that middleware thus runs first.