cache_page不生效的主因是中间件顺序错误和视图类型不匹配:UpdateCacheMiddleware须置MIDDLEWARE首位,FetchFromCacheMiddleware须紧随CommonMiddleware之后;仅函数视图直接支持,类视图需用cache_page(900)(MyView.as_view())包裹as_view()调用。

cache_page 装饰器不生效?先盯死中间件顺序和视图类型
它不是“配完 Redis 就自动缓存”,而是依赖请求生命周期中两个中间件的严格协作。UpdateCacheMiddleware 必须在 MIDDLEWARE 列表最顶部,FetchFromCacheMiddleware 必须紧接在 CommonMiddleware 之后、SecurityMiddleware 之前。中间插一个 SessionMiddleware 或 AuthenticationMiddleware,整个链路就断了,缓存彻底跳过。
只对函数视图生效;类视图必须写成 path('api/', cache_page(900)(MyView.as_view())),不能直接装饰类定义。另外,@cache_page 默认忽略 Cookie 和 Authorization 头——登录页用它基本等于裸奔,A 用户可能看到 B 用户的缓存响应。
- GET 参数(如
?page=2)会自动参与键生成,但带 CSRF token 或时间戳的前端动态参数会让每次请求键都不同,缓存形同虚设 - 装饰器参数单位是秒,传
"15m"或timedelta直接报TypeError - 同一 URL 上混用
cache_page(60)和cache_page(300),后注册的会覆盖前者的缓存,Django 不区分 timeout 差异
CACHES 配置错一个字符,cache.get() 就静默返回 None
Django 默认不报 Redis 连接失败,而是悄悄降级到 LocMemCache(进程内内存缓存)。你调 cache.set() 成功、cache.get() 却返回 None,八成是配置没走通。
-
BACKEND必须是"django_redis.cache.RedisCache",不是"django.core.cache.backends.redis.RedisCache"(后者是 Django 5.0+ 原生支持,但当前稳定版缺连接池和压缩能力) -
LOCATION必须带协议头:"redis://127.0.0.1:6379/1",不能只写"127.0.0.1:6379";漏掉末尾/1会连到 DB 0,可能被其他服务污染 - 开了密码必须写全:
"redis://:mypass@127.0.0.1:6379/1",冒号前留空表示无用户名 -
OPTIONS里漏掉"CLIENT_CLASS": "django_redis.client.DefaultClient",会导致序列化失败,cache.get()静默返回None
验证方式:进 python manage.py shell,执行 from django.core.cache import cache; cache.set('test', 'ok', 30); print(cache.get('test'))。输出 None?立刻检查 cache.client.connection_pool.get_connection().connect() 是否抛异常。
立即学习“Python免费学习笔记(深入)”;
全站缓存要开中间件对,但开发环境必须关
全站缓存靠 UpdateCacheMiddleware 和 FetchFromCacheMiddleware 成对工作,前者在最前、后者在最后,中间夹着 CommonMiddleware。少一个或顺序错,缓存完全不触发。
开发时务必关闭——静态资源、CSRF token、调试信息一旦被缓存,轻则表单提交失败,重则界面错乱、数据错位。它还依赖响应头里的 Cache-Control,视图里如果手动写了 response['Cache-Control'] = 'no-cache',全站缓存自动失效。
-
CACHE_MIDDLEWARE_KEY_PREFIX建议设个业务前缀(如"site"),避免和其他缓存 key 冲突 -
CACHE_MIDDLEWARE_ALIAS指定用哪个 cache backend(比如"default"),不配就默认用"default" - 它缓存的是完整 HTTP 响应,包括状态码、头、Body,所以不适合含用户态的页面(如个人中心)
缓存键设计不当,清理时根本找不到要删的 key
模板 {% cache %} 和 cache_page 生成的 key 是 Django 内部拼的,不暴露、不可预测。想主动清理?不能靠猜,得靠命名约定 + 前缀控制。
- 模板缓存加可预测前缀:
{% cache 300 "product_sidebar" product.id %}→ 实际 key 类似cache_product_sidebar_123,清理时cache.delete("cache_product_sidebar_123")就行 - 若用了
KEY_PREFIX(如"myapp"),实际 key 是"myapp:cache_sidebar_1_/home/",清理时必须带上前缀 - 别在
{% cache %}参数里传request整体——它不可哈希;改用request.user.id、request.GET.get("q")等具体字段 - 传
None或datetime会报TypeError: unhashable type,必须提前转成字符串或 ID
真正麻烦的不是设缓存,而是清理时机和范围——Django 不会自动感知数据变更,更新商品价格后,所有含该商品的页面缓存都得你手动清掉。


















