Django中间件排序的实用规则是什么?

32

官方文档有点混乱:'before'和'after'用于在元组中排序MiddleWare,但在某些地方'before'和'after'是指请求-响应阶段。此外,“should be first/last”被混合使用,不清楚应该使用哪个作为“first”。

我理解其中的区别......但对于Django中的新手来说似乎太复杂了。

您能否建议一些内置中间件类的正确排序(假设我们启用了所有中间件),并最重要的是解释为什么一个中间件在另一个中间件之前/之后?

以下是列表以及我在文档中找到的信息:

  1. UpdateCacheMiddleware
    • 在那些修改“Vary:”SessionMiddlewareGZipMiddlewareLocaleMiddleware的中间件之前
  2. GZipMiddleware
    • 在可能更改或使用响应正文的任何中间件之前
    • UpdateCacheMiddleware之后:修改“Vary:”
  3. ConditionalGetMiddleware
    • CommonMiddleware之前:当USE_ETAGS=True时使用其'Etag:'头
  4. SessionMiddleware
    • UpdateCacheMiddleware之后:修改“Vary:”
    • TransactionMiddleware之前:这里不需要事务
  5. LocaleMiddleware,靠近顶部,在SessionMiddlewareCacheMiddleware之后
    • UpdateCacheMiddleware之后:修改“Vary:”
    • SessionMiddleware之后:使用会话数据
  6. CommonMiddleware
    • 在任何可能更改响应的中间件之前(它计算ETags)
    • GZipMiddleware之后,因此它不会对压缩的内容计算E-Tag
    • 靠近顶部:当APPEND_SLASHPREPEND_WWW时重定向
  7. CsrfViewMiddleware
    • 在假定已处理了CSRF攻击的任何视图中间件之前
  8. AuthenticationMiddleware
    • SessionMiddleware 之后:使用会话存储
  9. MessageMiddleware
    • SessionMiddleware 之后:可以使用基于会话的存储
  10. XViewMiddleware
  11. TransactionMiddleware
    • 在使用DB的MW之后:SessionMiddleware(可配置为使用DB)
    • 所有*CacheMiddleWare不受影响(例外:使用自己的DB游标)
  12. FetchFromCacheMiddleware
    • 在修改'Vary:'的那些之后,如果使用它们来选择缓存哈希键的值
    • AuthenticationMiddleware 之后,因此可以使用 CACHE_MIDDLEWARE_ANONYMOUS_ONLY
  13. FlatpageFallbackMiddleware
    • 底部:最后的手段
    • 使用DB,但对于TransactionMiddleware不是问题 (是吗?)
  14. RedirectFallbackMiddleware
    • 底部:最后的手段
    • 使用DB,但对于TransactionMiddleware不是问题 (是吗?)

(我将添加建议到此列表中以便将它们收集在一个地方)


3
因为消息框架可能使用基于会话的后端来存储消息,所以 MessageMiddleware 需要放在 SessionMiddleware 之后。 - Madison Caldwell
这应该是一个社区问题,因为没有单个人有一个正确的答案 :) 然而,我看不到复选框。 - kolypto
我同意术语很令人困惑。也许“内部”和“外部”更合适。“设置.MIDDLEWARE_CLASSES”中靠近开头的那些是“外部”的;靠近结尾的那些是“内部”的。这与Django文档中的图形描述相匹配,并且也代表了中间件在执行时可以设置一个环境,在其中后续中间件将会操作。 - Aryeh Leib Taurog
3
为什么这个问题没有数百颗星星和赞,我永远不会知道!谢谢! - mkoistinen
2
Django在两年时间里发生了很大变化,有没有指向一个相同但更近期的资源的提示?谢谢,+1。 - Joseph Victor Zammit
也许在顶部使用SecurityMiddleware - Ivan Ogai
2个回答

4
设置顺序时最困难的部分是必须同时考虑两个方向。我认为这是设计上的缺陷,个人而言,我会选择单独的请求响应中间件顺序(这样就不需要像FetchFromCacheMiddlewareUpdateCacheMiddleware这样的hack)。
但无论如何,整个想法是让您的请求按照自上而下的顺序通过中间件列表进行process_requestprocess_view。对于process_responseprocess_exception,则以相反的顺序传递您的响应。
使用UpdateCacheMiddleware时,这意味着任何更改HTTP请求中Vary标头的中间件都应该在其前面。如果您在此处更改顺序,则某些用户可能会获取其他用户的缓存页面。
如何找出一个中间件是否更改了Vary标头?您可以希望有文档可用,或者只需查看源代码。通常很明显 :)

Django 1.10使用新的“MIDDLEWARE”方法分离请求和响应设置。详见:https://docs.djangoproject.com/en/1.10/releases/1.10/#new-style-middleware - Ian Clark
我尝试了中间件的每个顺序,但正如你所说,用户二得到了为用户一缓存的结果,并且数据库表中的任何新更改都没有反映在缓存中,它仍然使用相同的旧未过期的缓存。我在这里发布了我的问题,你能帮忙吗??拜托了..我已经挣扎了相当长的时间https://stackoverflow.com/q/70320750/8315427 - reindeer

2

有一个技巧可以保护你的数据,就是将TransactionMiddleware放在列表中的适当位置,以便它不能回滚其他中间件已提交到数据库的更改,这些更改无论视图是否引发异常都应该被提交。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接