Django站点缓存致用户名显示异常,如何为已认证用户禁用缓存?
最优解决方案分析
这个问题我之前也碰到过类似场景——全站缓存确实能大幅提升性能,但遇到用户个性化内容(比如导航栏的用户名)就容易踩缓存串数据的坑。给你两个针对性的方案,你可以根据自己的站点情况选择:
方案一:对已认证用户直接禁用全站缓存
如果你的站点只有导航栏有用户个性化内容,其他部分认证用户和匿名用户看到的内容一致,或者认证用户的访问量占比不高,这个方案简单直接,不需要改模板,只需要加个自定义中间件就行。
实现步骤:
- 新建一个中间件类,用来判断当前用户是否已认证,如果是,就告诉Django的缓存中间件跳过缓存逻辑:
# 在你的app里新建middleware.py文件,或者直接放到settings所在的文件里 class SkipCacheForAuthenticatedUsersMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): # 如果用户已登录,禁用缓存中间件的读写操作 if request.user.is_authenticated: request._cache_update_cache = False request._cache_fetch_from_cache = False response = self.get_response(request) return response
- 修改settings里的中间件顺序,必须把这个自定义中间件放在UpdateCacheMiddleware的前面(因为Django中间件请求阶段是从上到下执行的,要先判断用户状态再触发缓存逻辑):
MIDDLEWARE = [ # 先放自定义的中间件 'your_app.middleware.SkipCacheForAuthenticatedUsersMiddleware', # 然后是Django的缓存中间件 'django.middleware.cache.UpdateCacheMiddleware', # 其他中间件... 'django.middleware.cache.FetchFromCacheMiddleware', ]
这个方案的好处是:匿名用户依然能享受到全站缓存的性能提升,认证用户的页面会实时渲染,不会出现用户名串了的问题。
方案二:局部缓存,排除导航栏部分
如果认证用户访问量很高,你不想放弃对他们的页面缓存,只是要排除导航栏这个个性化区域,那可以用Django的模板级缓存,只缓存页面的公共内容部分,导航栏动态渲染。
实现步骤:
- 先把settings里的全站缓存中间件(
UpdateCacheMiddleware和FetchFromCacheMiddleware)移除,因为全站缓存会覆盖模板级缓存的逻辑。 - 在模板里用
{% cache %}标签包裹公共内容,导航栏部分不包裹:
{% load cache %} <!-- 只缓存所有用户内容一致的部分,缓存时间和之前的6小时一致 --> {% cache 21600 homepage_common %} <div class="main-content"> <!-- 这里放首页的公共内容,比如文章列表、公告等 --> </div> {% endcache %} <!-- 导航栏部分不缓存,动态渲染用户名 --> <nav class="site-nav"> <a href="/">首页</a> <a href="/about">关于</a> {% if user.is_authenticated %} <span class="user-info">欢迎回来,{{ user.username }}</span> <a href="/logout">退出</a> {% else %} <a href="/login">登录</a> {% endif %} </nav>
这个方案的好处是:不管是匿名还是认证用户,都能缓存公共内容,同时导航栏始终显示当前用户的正确信息,性能和个性化需求都兼顾到了。
哪个方案更优?
- 如果你的站点认证用户占比低,或者除了导航栏之外还有很多个性化内容,选方案一,实现成本低,逻辑简单。
- 如果你的站点认证用户占比高,且大部分页面内容是公共的,只有导航栏等小区域个性化,选方案二,能最大化利用缓存提升性能。
内容的提问来源于stack exchange,提问作者Brachamul
相关产品推荐
相关产品推荐

