cache_page 怎么决定缓存几份?哪些响应不会被缓存?带登录信息的页面会不会缓存串了?这篇分别试页面缓存、Vary、低级缓存和模板片段缓存,并复现两个容易出事故的情形。
第 1 次: page 1 q=1 第 2 次(同 URL): page 1 q=1 换 ?q=2: page 2 q=2 视图执行次数: 2 响应头 Cache-Control: max-age=60 Expires: True Vary: None Cache-Control 里的 max-age 与 cache_page(60) 一致: True
装饰在视图上的整页缓存。key 包含完整 URL(含查询串),所以带跟踪参数的 URL 会各存一份。
X-Device: phone → device 1 phone | desktop → device 2 desktop | 再 phone → device 1 phone | 视图执行次数: 2 (phone 命中缓存,desktop 是另一份) Accept-Language: en → lang 1 en | zh → lang 1 en | 视图执行次数: 1 (zh 拿到了 en 的缓存!因为没有 LocaleMiddleware 切换语言) USE_I18N = True
需要按语言缓存时,要用 LocaleMiddleware 让语言激活;需要按登录用户缓存时,用 vary_on_cookie——更稳妥的做法是,对有用户个性化内容的页面不用整页缓存,改用片段缓存。
POST 两次,视图执行次数: 2 500 响应两次,视图执行次数: 2 (错误响应不缓存) 视图 set_cookie 两次,视图执行次数: 1 响应 Vary: None 第二次仍带 Set-Cookie: True
读 Django 6.1.1 的缓存中间件源码:不缓存的情形有——流式响应、状态码不是 200/304、响应设置了 cookie 且 Vary: Cookie、Cache-Control 含 private / no-cache / no-store、Vary: *。视图只是 set_cookie 而没有 Vary: Cookie 时不在此列,所以会被缓存(上面的实测)。
id=1 → computed-1 id=1 → computed-1 id=2 → computed-2 id=1 → computed-1 计算次数: 2
user 1, counter=1: [计算 1] user 1, counter=2(命中缓存): [计算 1] user 2, counter=3(另一个 key): [计算 3] 片段的 key: template.cache.sidebar.6709aa7b0015b3f2257cda58f6ae8ed0
片段缓存的 key 由片段名和额外变量的哈希组成,变量里放用户 id 即可按用户区分。