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 缓存查询结果、计算结果 ⭐⭐⭐⭐⭐
视图缓存 匿名用户静态页面 ⭐⭐⭐
模板片段 局部动态内容 ⭐⭐⭐⭐
站点缓存 完全静态网站 ⭐⭐
相关推荐
AC赳赳老秦5 小时前
网页公开附件自动采集:OpenClaw 批量下载页面内嵌 Word/Excel 附件,统一格式后结构化入库
java·python·word·php·excel·deepseek·openclaw
北斗落凡尘5 小时前
LangGraph 入门实战(3)
python·langchain
TAN-90°-5 小时前
Deep Learning for Computer Vision——Image Classification with Linear Classifiers
python·深度学习·算法·计算机视觉·线性回归
AINative软件工程5 小时前
LLM API 成本失控怎么办?工程师的实时异常检测指南
python
练习两年半的攻城狮5 小时前
LlamaIndex ResponseMode 深度解析
python·llamaindex
油丶酸萝卜别吃6 小时前
Redis 布隆过滤器快速实现
数据库·redis·缓存
阿pin6 小时前
Java随笔-红黑树
java·python·算法·红黑树
MC皮蛋侠客6 小时前
TDengine C++ 系列(8):流式计算与最新值缓存——库内实时处理
c++·缓存·tdengine
2603_965148116 小时前
eBay商品数据API:寻找海外仓与价格洼地
大数据·人工智能·windows·python·microsoft