Django 缓存详解与应用方法

Django 提供了强大且灵活的缓存框架,可以显著提升 Web 应用性能,尤其适用于高并发、数据读多写少的场景(如你提到的 28 万行数据查询页面)。


一、Django 缓存支持的后端类型

缓存后端 说明 适用场景
django.core.cache.backends.locmem.LocMemCache 本地内存缓存(默认) 单进程开发环境
django.core.cache.backends.redis.RedisCache Redis 缓存(推荐生产使用) 多进程、分布式部署
django.core.cache.backends.memcached.PyLibMCCacheMemcachedCache 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.py

CACHES = {
    "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 cache

def 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️⃣ 方式四:站点级缓存(全站缓存)

自动缓存所有页面(需配合中间件)。

步骤:
  1. settings.py 中添加中间件(顺序很重要!):

    MIDDLEWARE = [
    'django.middleware.cache.UpdateCacheMiddleware', # 必须在最前
    'django.middleware.common.CommonMiddleware',
    # ... 其他中间件
    'django.middleware.cache.FetchFromCacheMiddleware', # 必须在最后
    ]

    缓存时间(秒)

    CACHE_MIDDLEWARE_SECONDS = 600

  2. 确保 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)

六、生产环境最佳实践

  1. 使用 Redis 而非内存缓存(支持多 worker 共享)
  2. 监控缓存命中率 (可通过 Redis INFO 命令)
  3. 避免缓存大对象(如 28 万行数据),只缓存元数据或分页结果
  4. 设置合理过期时间:高频变动数据设短(如 5 分钟),静态数据设长(如 1 小时)
  5. 在管理后台或数据导入脚本中主动清除缓存

七、常见问题排查

Q:缓存没生效?

  • 检查 CACHES 配置是否正确
  • 确认 Redis/Memcached 服务已启动
  • 查看日志是否有连接错误

Q:缓存了不该缓存的内容?

  • 检查是否误用了 @cache_page 到含用户信息的页面
  • 使用 vary_on_cookievary_on_headers 控制缓存变体

Q:内存占用过高?

  • 避免缓存 QuerySet(应缓存 .values() 或列表)
  • 设置合理的 timeout
  • 使用 Redis 的 LRU 淘汰策略

总结

缓存层级 适用场景 推荐度
底层 API 缓存查询结果、计算结果 ⭐⭐⭐⭐⭐
视图缓存 匿名用户静态页面 ⭐⭐⭐
模板片段 局部动态内容 ⭐⭐⭐⭐
站点缓存 完全静态网站 ⭐⭐
相关推荐
野生工程师3 小时前
【Python爬虫基础-3】数据解析
开发语言·爬虫·python
道19933 小时前
python实现电脑手势识别截图
开发语言·python
shixian10304114 小时前
conda安装Django+pg运行环境
python·django·conda
jiaoxingk4 小时前
Django 接口文档生成:Swagger 与 ReDoc 全面说明
python·django
熊文豪4 小时前
Docker 缓存优化:通过 cpolar 内网穿透服务远程管理 Redis
redis·缓存·docker·cpolar
CodeCraft Studio4 小时前
国产化Excel开发组件Spire.XLS教程:Python将列表导出为CSV文件(含一维/二维/字典列表)
开发语言·python·excel·csv·spire.xls·列表导出为csv
Blossom.1184 小时前
大模型知识蒸馏实战:从Qwen-72B到Qwen-7B的压缩艺术
大数据·人工智能·python·深度学习·算法·机器学习·pygame
刘逸潇20055 小时前
Socket:TCP/UDP通信详解
python·websocket·udp·tcp