Django 2.0仅用数据库缓存耗时页面,禁用浏览器缓存相关问题求助
Hey there! Let's break down how to meet all your caching goals for those slow-loading Django pages. We'll use Django's built-in database cache backend, pair it with view-level caching, and tweak response headers to keep browsers from holding onto outdated content—while still letting static files like JS cache normally.
第一步:配置数据库缓存后端
First, we need to set up Django to use your database as the cache store. Edit your settings.py:
CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.db.DatabaseCache', 'LOCATION': 'page_cache_table', # 我们要创建的缓存表名称 } }
然后运行命令在数据库中创建缓存表:
python manage.py createcachetable
第二步:缓存慢页面+禁止浏览器缓存
我们用Django的cache_page装饰器把页面内容存在数据库里,但得加个自定义装饰器阻止浏览器缓存(毕竟浏览器没法知道你的数据库什么时候更新)。
在views.py(或单独的decorators.py文件)里创建自定义装饰器:
from django.views.decorators.cache import cache_page def no_browser_cache(view_func): def wrapped_view(request, *args, **kwargs): response = view_func(request, *args, **kwargs) # 告诉浏览器完全不要缓存这个页面 response['Cache-Control'] = 'no-cache, no-store, must-revalidate' response['Pragma'] = 'no-cache' response['Expires'] = '0' # 确保点击返回按钮时浏览器也会重新验证内容 response['Vary'] = 'Cookie, Accept-Encoding' return response return wrapped_view
现在把两个装饰器都应用到慢加载视图上:
@no_browser_cache @cache_page(60 * 60 * 24) # 缓存24小时——我们会在数据库变更时手动失效缓存 def slow_loading_page(request): # 这里放你的耗时视图逻辑 return render(request, 'slow_page.html')
如果是类视图,用method_decorator来装饰:
from django.views.generic import TemplateView from django.utils.decorators import method_decorator @method_decorator(no_browser_cache, name='dispatch') @method_decorator(cache_page(60*60*24), name='dispatch') class SlowPageView(TemplateView): template_name = 'slow_page.html'
第三步:预存页面到数据库缓存
为了提前把页面存进缓存(避免用户第一次访问时遇到慢加载),我们创建一个自定义管理命令。
在你的app里创建management/commands/precache_pages.py:
from django.core.management.base import BaseCommand from django.test.client import Client class Command(BaseCommand): help = '把慢加载页面预存到数据库缓存' def handle(self, *args, **options): client = Client() # 替换成你的慢页面URL列表 slow_urls = ['/slow-page/', '/another-slow-page/'] for url in slow_urls: client.get(url) self.stdout.write(f'成功预缓存 {url}')
运行这个命令:
python manage.py precache_pages
它会访问每个URL,把渲染好的页面存进数据库缓存里。
第四步:数据库变更时自动失效缓存
当相关数据库模型更新或删除时,我们需要清除对应页面的缓存。用Django的信号来实现这个逻辑。
在models.py(或单独的signals.py文件)里:
from django.db.models.signals import post_save, post_delete from django.dispatch import receiver from django.core.cache import cache from django.urls import reverse from .models import YourModel # 替换成会触发页面更新的模型 @receiver(post_save, sender=YourModel) @receiver(post_delete, sender=YourModel) def invalidate_slow_page_cache(sender, instance, **kwargs): # 获取慢页面的缓存键(Django的cache_page用特定格式生成键) # 把reverse里的参数换成你的URL名称 cache_key = f'views.decorators.cache.cache_page.86400.django.http.request.HttpRequest.GET.{reverse("slow-page-name")}' cache.delete(cache_key) # 如果有多个慢页面,给每个页面重复cache.delete()操作 # 或者用cache.clear()清空所有缓存(谨慎使用!) # cache.clear()
要确认准确的缓存键,可以在Django shell里运行cache.keys(),找以views.decorators.cache.cache_page开头的条目。
第五步:保留静态文件的浏览器缓存
Django在生产环境下默认支持这个需求。更新settings.py使用manifest存储,它会给静态文件名加上唯一哈希(这样只有当文件内容改变时,浏览器才会重新加载):
import os from django.conf import settings STATIC_URL = '/static/' STATIC_ROOT = os.path.join(settings.BASE_DIR, 'staticfiles') if not settings.DEBUG: STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.ManifestStaticFilesStorage'
这个设置让浏览器可以长期缓存JS/CSS文件,因为文件名会随内容变化而更新。
验证所有目标是否达成
我们来核对你的需求:
- ✅ 预存页面到数据库缓存:
precache_pages命令和cache_page装饰器搞定这件事 - ✅ 向用户提供缓存页面:
cache_page会自动从数据库缓存中拉取内容返回给用户 - ✅ 浏览器不缓存这些页面:
no_browser_cache装饰器设置的响应头会强制浏览器每次都从服务器获取最新内容 - ✅ 保留JS等文件的浏览器缓存:
ManifestStaticFilesStorage确保静态文件被长期缓存,但内容变更时会自动更新 - ✅ 返回按钮不使用浏览器缓存:
Cache-Control和Vary头让浏览器即使点击返回按钮也会重新验证内容
内容的提问来源于stack exchange,提问作者mamazieiizmilzeu

