Django URL缓存仅在F5刷新页面时生效的问题咨询
解决Django URL缓存仅F5刷新生效的问题
看起来你遇到的问题是cache_page装饰器的缓存效果只在手动刷新(F5)时触发,通过jQuery跳转时没生效?咱们一步步排查解决:
首先,检查Django缓存基础配置是否正确
cache_page依赖Django的缓存后端和中间件配置,先确认这两点:
1. 缓存后端配置
在settings.py里确保你已经配置了有效的缓存后端,比如本地内存缓存(开发环境用):
CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', 'LOCATION': 'unique-snowflake', } }
生产环境可以换成Redis、Memcached或者文件缓存,只要配置正确就行。
2. 缓存中间件顺序
中间件的顺序非常关键,UpdateCacheMiddleware必须放在最前面,FetchFromCacheMiddleware要放在最后面,否则缓存逻辑会失效:
MIDDLEWARE = [ 'django.middleware.cache.UpdateCacheMiddleware', # 其他中间件(比如CommonMiddleware、CsrfViewMiddleware等) 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', # ... 其他中间件 ... 'django.middleware.cache.FetchFromCacheMiddleware', ]
验证缓存是否真的在工作
先排除“假缓存”的情况:在你的views.alp视图函数里加个打印或者日志,比如:
import logging logger = logging.getLogger(__name__) def alp(request, alp): logger.info(f"Rendering alp page for: {alp}") # 你的视图逻辑... return render(request, 'my_template.html', {'alp': alp})
然后:
- 第一次访问
/a/,看日志是否打印 - 直接通过jQuery跳转
/a/,看日志是否再次打印 - 按F5刷新
/a/,看日志是否打印
如果只有第一次访问打印,说明缓存其实生效了——可能是你误以为没生效(比如页面内容没变化,但缓存确实在工作);如果jQuery跳转时日志又打印了,那说明缓存没命中,继续往下看。
检查浏览器缓存响应头
cache_page(60*15)应该自动给响应添加Cache-Control: max-age=900和Expires头,你可以在浏览器开发者工具的Network标签里查看:
- 访问页面时,看响应头里的
Cache-Control、Expires、ETag这些字段是否存在 - 如果这些头缺失,说明
cache_page装饰器没正确生效,可能是中间件顺序错了,或者视图被其他装饰器(比如never_cache)覆盖了
排查jQuery跳转的问题
假设你的完整jQuery跳转代码是这样:
$('#btn_custom').click(function (e) { e.preventDefault(); location.href = $('#url_custom').data('custom'); });
这种跳转和正常点击链接是一样的,浏览器应该会使用缓存。如果还是没命中,可能是:
- 浏览器之前的请求带了
Cache-Control: no-cache之类的头(比如某些插件或者浏览器设置导致) - 你的视图里有动态内容(比如用户会话相关的内容),导致Django无法缓存页面(因为缓存页面是针对所有用户的,带会话的请求会跳过缓存)
如果是会话的问题,你可以在视图里用vary_on_cookie装饰器,或者确保视图不依赖会话数据:
from django.views.decorators.vary import vary_on_cookie @cache_page(60*15) @vary_on_cookie def alp(request, alp): # 视图逻辑
最后,强制浏览器缓存页面
如果上面的步骤都没问题,你可以手动在视图里添加缓存头,加强浏览器的缓存行为:
from datetime import datetime, timedelta @cache_page(60*15) def alp(request, alp): response = render(request, 'my_template.html', {'alp': alp}) # 强制浏览器缓存15分钟 response['Cache-Control'] = 'public, max-age=900' response['Expires'] = (datetime.utcnow() + timedelta(minutes=15)).strftime('%a, %d %b %Y %H:%M:%S GMT') return response
内容的提问来源于stack exchange,提问作者David Foie Gras
相关产品推荐
相关产品推荐

