Django 缓存详解与应用方法
Django 提供了强大且灵活的缓存框架,可以显著提升 Web 应用性能,尤其适用于高并发、数据读多写少的场景(如你提到的 28 万行数据查询页面)。
一、Django 缓存支持的后端类型
| 缓存后端 | 说明 | 适用场景 |
|---|---|---|
django.core.cache.backends.locmem.LocMemCache | 本地内存缓存(默认) | 单进程开发环境 |
django.core.cache.backends.redis.RedisCache | Redis 缓存(推荐生产使用) | 多进程、分布式部署 |
django.core.cache.backends.memcached.PyLibMCCache 或 MemcachedCache | Memcached | 高性能、简单键值存储 |
django.core.cache.backends.filebased.FileBasedCache | 文件系统缓存 | 无 Redis/Memcached 的轻量环境 |
django.core.cache.backends.dummy.DummyCache | 伪缓存(不实际缓存) | 开发调试 |
✅ 生产环境强烈推荐使用 Redis:功能丰富、持久化、支持过期、集群等。
二、配置缓存(settings.py)
示例 1:使用 Redis(推荐)
首先安装依赖:
pip install redis django-redis然后在 settings.py 中配置:
# settings.pyCACHES = {"default": {"BACKEND": "django_redis.cache.RedisCache","LOCATION": "redis://127.0.0.1:6379/1", # 数据库存储在 DB 1"OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient",},"KEY_PREFIX": "myproject", # 可选:避免 key 冲突}
}# 可选:设置缓存超时时间(秒)
CACHE_TTL = 60 * 60 # 1 小时示例 2:本地内存缓存(仅开发)
CACHES = {'default': {'BACKEND': 'django.core.cache.backends.locmem.LocMemCache','LOCATION': 'unique-snowflake', # 唯一标识}
}示例 3:文件缓存(无 Redis 时备用)
CACHES = {'default': {'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache','LOCATION': '/var/tmp/django_cache',}
}💡 确保目录存在且可写:
sudo mkdir -p /var/tmp/django_cache && sudo chmod 777 /var/tmp/django_cache
三、Django 缓存的四种使用方式
1️⃣ 方式一:底层缓存 API(最灵活)
适用于缓存任意 Python 对象(如查询结果、计算结果)。
from django.core.cache import cache# 写入缓存(key, value, timeout)
cache.set('my_key', 'Hello World', timeout=300) # 5分钟# 读取缓存
value = cache.get('my_key')
if value is None:# 缓存未命中,重新计算并写入value = expensive_computation()cache.set('my_key', value, timeout=300)# 删除缓存
cache.delete('my_key')# 批量操作
cache.set_many({'a': 1, 'b': 2}, timeout=60)
cache.get_many(['a', 'b'])✅ 应用示例:缓存筛选选项(解决你 10 秒加载问题)
# views.py
from django.core.cache import cachedef summary_search(request):# 尝试从缓存获取筛选选项filter_options = cache.get('summary_filter_options')if filter_options is None:filter_options = {'discipline_options': list(Summary_data.objects.exclude(discipline='').values_list('discipline', flat=True).distinct()),'province_options': list(Summary_data.objects.exclude(province_name='').values_list('province_name', flat=True).distinct()),# ... 其他选项}cache.set('summary_filter_options', filter_options, timeout=3600) # 缓存1小时# 使用 filter_options ...🔄 数据更新时清除缓存(在导入或管理后台保存后):
from django.core.cache import cache cache.delete('summary_filter_options')
2️⃣ 方式二:视图级缓存(整页缓存)
缓存整个视图的 HTTP 响应。
from django.views.decorators.cache import cache_page@cache_page(60 * 15) # 缓存 15 分钟
def my_view(request):# 复杂查询或渲染return render(request, 'template.html', context)⚠️ 注意:如果页面包含用户特定内容(如登录状态),不要使用整页缓存!
3️⃣ 方式三:模板片段缓存
只缓存 HTML 中的某一部分(如侧边栏、热门文章)。
<!-- template.html -->
{% load cache %}{% cache 500 sidebar request.user.id %}<!-- 这里是动态侧边栏内容 --><div>欢迎, {{ user.username }}</div>
{% endcache %}500:缓存时间(秒)sidebar:缓存片段名称request.user.id:缓存 key 的变量部分(不同用户看到不同内容)
4️⃣ 方式四:站点级缓存(全站缓存)
自动缓存所有页面(需配合中间件)。
步骤:
- 在
settings.py中添加中间件(顺序很重要!):
MIDDLEWARE = ['django.middleware.cache.UpdateCacheMiddleware', # 必须在最前'django.middleware.common.CommonMiddleware',# ... 其他中间件'django.middleware.cache.FetchFromCacheMiddleware', # 必须在最后
]# 缓存时间(秒)
CACHE_MIDDLEWARE_SECONDS = 600- 确保
CACHES已配置。
❗ 仅适用于完全静态或匿名用户页面,登录用户页面会出错!
四、缓存 Key 设计建议
- 使用有意义的前缀:
summary:filter_options - 包含版本号便于清理:
v1:summary_options - 避免 key 冲突:不同模块用不同命名空间
key = f"summary:filter_options:v1"
cache.set(key, data, timeout=3600)五、缓存失效策略
| 场景 | 方法 |
|---|---|
| 数据更新后 | cache.delete('key') |
| 批量清除 | cache.clear()(慎用!) |
| 自动过期 | 设置 timeout 参数 |
| 版本升级 | 修改 key 前缀(如 v1 → v2) |
六、生产环境最佳实践
- 使用 Redis 而非内存缓存(支持多 worker 共享)
- 监控缓存命中率(可通过 Redis
INFO命令) - 避免缓存大对象(如 28 万行数据),只缓存元数据或分页结果
- 设置合理过期时间:高频变动数据设短(如 5 分钟),静态数据设长(如 1 小时)
- 在管理后台或数据导入脚本中主动清除缓存
七、常见问题排查
Q:缓存没生效?
- 检查
CACHES配置是否正确 - 确认 Redis/Memcached 服务已启动
- 查看日志是否有连接错误
Q:缓存了不该缓存的内容?
- 检查是否误用了
@cache_page到含用户信息的页面 - 使用
vary_on_cookie或vary_on_headers控制缓存变体
Q:内存占用过高?
- 避免缓存 QuerySet(应缓存
.values()或列表) - 设置合理的
timeout - 使用 Redis 的 LRU 淘汰策略
总结
| 缓存层级 | 适用场景 | 推荐度 |
|---|---|---|
| 底层 API | 缓存查询结果、计算结果 | ⭐⭐⭐⭐⭐ |
| 视图缓存 | 匿名用户静态页面 | ⭐⭐⭐ |
| 模板片段 | 局部动态内容 | ⭐⭐⭐⭐ |
| 站点缓存 | 完全静态网站 | ⭐⭐ |
