添加Django缓存中间件的正确顺序是什么?

时间:2019-09-20 13:44:37

标签: django

我正在尝试将缓存添加到我的Django项目中,但是我无法理解middleware ordering上的文档。考虑以下MIDDLEWARE列表,该列表通常是默认设置:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'simple_history.middleware.HistoryRequestMiddleware'
]

如果我正确理解this piece of documentation,则应该在MIDDLEWARE列表中添加三个新条目。我的案件有不只一种适当的订购吗?

1 个答案:

答案 0 :(得分:1)

默认的 startproject middleware 是:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

三个 per-site cache middleware 给出如下:

MIDDLEWARE = [
    'django.middleware.cache.UpdateCacheMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.cache.FetchFromCacheMiddleware',
]

当我们讨论缓存时,还有与 ConditionalGetMiddleware 相关的 conditional view processing

MIDDLEWARE = [
    'django.middleware.http.ConditionalGetMiddleware'
]

问题是,将所有这些组合成一个 MIDDLEWARE 列表的 proper order 是什么? Django 文档给出了两条特定于缓存的规则:

  • UpdateCacheMiddleware 必须之前“任何其他可能向 Vary 标头添加内容的中间件”(以及 SessionMiddlewareGZipMiddleware、{ {1}} 做)
  • LocaleMiddleware 需要运行 after 不同的中间件 FetchFromCacheMiddleware

虽然如果您有其他自定义内容可能会更微妙,但基于默认值的最自然方法是将所有其他中间件括在缓存中。但是我们将把 Vary 放在最上面,因为它只是检查/重定向一些可以更好地完成的东西[例如nginx] 无论如何都要包装 Django 本身。

SecurityMiddleware 可能已经包含在 CommonMiddleware 列表中的正确位置,因此很容易。

startproject 是骗子; Middleware ordering 提示的一个单独部分说它“在 GZipMiddleware […] 之后”,但总体上“在任何可能改变响应的中间件之前”,这有点奇怪,但无论如何……。 (显然 GZip 中间件无论如何都是 discouraged/problematic。)

最后这是我得到的:

ConditionalGetMiddleware

请注意,MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.middleware.cache.UpdateCacheMiddleware', 'django.middleware.gzip.GZipMiddleware', # Caution: BREACH attack? 'django.middleware.http.ConditionalGetMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.cache.FetchFromCacheMiddleware', ] ConditionalGetMiddleware 之间至少有一个 odd interaction,因为如果/当渲染被 304 响应替换时,前者可能会阻止后者实际缓存渲染.

所以也许更好:

UpdateCacheMiddleware

……避免使用 Gzip 并在 HTTP 服务器层处理 HTTPS/HSTS 内容。