加cache-control仍慢是因为它只缓存响应结果,不跳过视图执行;而cache_page可完全绕过视图逻辑,实现真正提速。

直接加 Cache-Control 头不一定能提速,尤其当视图本身要花 2 秒执行、数据库查了 15 次时——缓存的是慢结果,不是快响应。
为什么加了 Cache-Control 还是慢?
常见错觉:只要加上 Cache-Control: public, max-age=3600,浏览器就该秒开。但实际中,Django 视图函数仍需完整执行一遍才能生成响应体,缓存只发生在「生成之后」。如果视图里有未优化的 Book.objects.all() 或嵌套 for book in books: book.author.name,首次请求照样卡顿,且后续缓存的也是这个慢结果。
关键点在于:Cache-Control 是 HTTP 层缓存,不跳过 Python 逻辑执行;它只影响「响应是否被复用」,不解决「响应怎么生成得快」。
- 浏览器或 CDN 缓存的是最终 HTTP 响应(含状态码、头、body),不是 Django 的中间状态
- 如果视图用了
request.user或timezone.now()等动态值,Cache-Control: public可能失效或导致脏数据 - Django 默认不自动设置
Vary头,若接口对不同用户返回不同内容,却用了public缓存,会出问题
什么时候该用 cache_page 而不是手动设 Cache-Control?
cache_page 是 Django 内置的视图级缓存装饰器,它在中间件层拦截请求,命中时直接返回缓存响应,完全跳过视图函数执行。相比手动写 Cache-Control 头,它更早介入、更省资源。
适用场景明确:公开、无用户态依赖、低频变更的数据接口,比如首页公告、产品分类列表、静态配置页。
- 正确用法:
@cache_page(60 * 15, key_prefix='api_v1')—— 自动加Cache-Control头,且绕过视图逻辑 - 别用在
@login_required视图上:缓存可能把 A 用户的页面返回给 B 用户 - 注意缓存键默认不含 GET 参数,如需区分
?category=books和?category=movies,得配合cache_page+cache_control(vary_on=['query_params'])或改用cache_page的cache参数指定带参数的缓存后端
局部缓存:模板片段 vs. 视图级 vs. 数据库查询级
“局部”不是指缓存一小段 HTML,而是指缓存链条中更靠前、更细粒度的一环。越靠近数据源头,收益越大。
-
模板片段缓存(
{% cache 300 "book_list" %}):适合渲染逻辑重、但数据变化少的区块,比如侧边栏推荐。缺点是仍要执行视图、查 DB、序列化,只是跳过了 render 步骤 -
视图级缓存(
@cache_page):跳过整个视图,但要求 URL 完全一致才命中;对分页接口(/api/books/?page=2)天然友好 -
数据库查询级缓存(
cache.get('book_ids')+Book.objects.filter(id__in=cached_ids)):最灵活,可控制缓存粒度(如按 author_id 缓存其所有书),但需要你主动管理键、失效逻辑,容易 stale
别把三者混用:比如既用 @cache_page 又在模板里套 {% cache %},后者根本不会执行。
容易被忽略的缓存陷阱
缓存不是开关,开了就稳。几个真实踩过的坑:
-
cache_page对 POST/PUT/DELETE 请求默认不生效(HTTP 规范要求),但如果你的前端误发了 POST 到本该 GET 的接口,缓存会静默失效,排查时发现“有时快有时慢” - 使用 Redis 作缓存后端时,
KEY_PREFIX配置错误会导致多个环境共用一套缓存键,测试环境刷缓存,线上跟着失效 - 在
settings.py中启用了'django.middleware.cache.FetchFromCacheMiddleware',但没配UpdateCacheMiddleware在前面,结果缓存永远不写入 - 用
cache.set('key', obj)直接存 ORM 实例,反序列化时可能丢失模型元信息或引发PickleError;应存obj.pk或序列化后的 dict
最麻烦的不是缓存没生效,而是缓存「生效了但内容不对」——比如认证中间件读了缓存里的未登录用户响应,返回了 403 页面给已登录用户。这类问题往往在线上压测或灰度发布时才暴露,调试成本远高于一开始选对缓存层级。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











