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 缓存查询结果、计算结果 ⭐⭐⭐⭐⭐
视图缓存 匿名用户静态页面 ⭐⭐⭐
模板片段 局部动态内容 ⭐⭐⭐⭐
站点缓存 完全静态网站 ⭐⭐
相关推荐
_深海凉_15 分钟前
LeetCode热题100-颜色分类
python·算法·leetcode
AC赳赳老秦37 分钟前
OpenClaw email技能:批量发送邮件、自动回复,高效处理工作邮件
运维·人工智能·python·django·自动化·deepseek·openclaw
zhaoshuzhaoshu1 小时前
Python 语法之数据结构详细解析
python
AI问答工程师1 小时前
Meta Muse Spark 的"思维压缩"到底是什么?我用 Python 复现了核心思路(附代码)
人工智能·python
zfan5202 小时前
python对Excel数据处理(1)
python·excel·pandas
小饕2 小时前
我从零搭建 RAG 学到的 10 件事
python
老歌老听老掉牙2 小时前
PyQt5+Qt Designer实战:可视化设计智能参数配置界面,告别手动布局时代!
python·qt
格鸰爱童话3 小时前
向AI学习项目技能(六)
java·人工智能·spring boot·python·学习
悟空爬虫-彪哥3 小时前
VRChat开发环境配置,零基础教程
python
数据知道3 小时前
《 Claude Code源码分析与实践》专栏目录
python·ai·github·claude code·claw code