Practical rules for Django MiddleWare ordering?
The official documentation is a bit messy: 'before' & 'after' are used for ordering MiddleWare in a tuple, but in some places 'before'&'after' refers to request-response phases. Also, 'should be first/last' are mixed and it's not clear which one to use as 'first'.
I do understand the difference.. however it seems to complicated for a newbie in Django.
Can you suggest some correct ordering for builtin开发者_运维知识库 MiddleWare classes (assuming we enable all of them) and — most importantly — explain WHY one goes before/after other ones?
here's the list, with the info from docs I managed to find:
UpdateCacheMiddleware
- Before those that modify 'Vary:'
SessionMiddleware
,GZipMiddleware
,LocaleMiddleware
- Before those that modify 'Vary:'
GZipMiddleware
- Before any MW that may change or use the response body
- After
UpdateCacheMiddleware
: Modifies 'Vary:'
ConditionalGetMiddleware
- Before
CommonMiddleware
: uses its 'Etag:' header whenUSE_ETAGS=True
- Before
SessionMiddleware
- After
UpdateCacheMiddleware
: Modifies 'Vary:' - Before
TransactionMiddleware
: we don't need transactions here
- After
LocaleMiddleware
, One of the topmost, after SessionMiddleware, CacheMiddleware- After
UpdateCacheMiddleware
: Modifies 'Vary:' - After
SessionMiddleware
: uses session data
- After
CommonMiddleware
- Before any MW that may change the response (it calculates ETags)
- After
GZipMiddleware
so it won't calculate an E-Tag on gzipped contents - Close to the top: it redirects when
APPEND_SLASH
orPREPEND_WWW
CsrfViewMiddleware
- Before any view middleware that assumes that CSRF attacks have been dealt with
AuthenticationMiddleware
- After
SessionMiddleware
: uses session storage
- After
MessageMiddleware
- After
SessionMiddleware
: can use Session-based storage
- After
XViewMiddleware
TransactionMiddleware
- After MWs that use DB:
SessionMiddleware
(configurable to use DB) - All
*CacheMiddleWare
is not affected (as an exception: uses own DB cursor)
- After MWs that use DB:
FetchFromCacheMiddleware
- After those those that modify 'Vary:' if uses them to pick a value for cache hash-key
- After
AuthenticationMiddleware
so it's possible to useCACHE_MIDDLEWARE_ANONYMOUS_ONLY
FlatpageFallbackMiddleware
- Bottom: last resort
- Uses DB, however, is not a problem for
TransactionMiddleware
(yes?)
RedirectFallbackMiddleware
- Bottom: last resort
- Uses DB, however, is not a problem for
TransactionMiddleware
(yes?)
(I will add suggestions to this list to collect all of them in one place)
The most difficult part is that you have to consider both directions at the same time when setting the order. I would say that's a flaw in the design and I personally would opt for a separate request
and response
middleware order (so you wouldn't need hacks like FetchFromCacheMiddleware
and UpdateCacheMiddleware
).
But... alas, it's this way right now.
Either way, the idea of it all is that your request passes through the list of middlewares in top-down order for process_request
and process_view
. And it passes your response through process_response
and process_exception
in reverse order.
With UpdateCacheMiddleware
this means that any middleware that changes the Vary
headers in the HTTP request should come before it. If you change the order here than it would be possible for some user to get a cached page for some other user.
How can you find out if the Vary
header is changed by a middleware? You can either hope that there are docs available, or simply look at the source. It's usually quite obvious :)
One tip that can save your hair is to put TransactionMiddleware in such place on the list, in which it isn't able to rollback changes commited to the database by other middlewares, which changes should be commited no matter if view raised an exception or not.
精彩评论