如何预填充Django中使用cache_page装饰的DRF ViewSet接口缓存
实现方案
1. 配置数据库缓存
首先修改settings.py中的缓存配置,替换默认的LocMemCache为数据库缓存:
CACHES = { "default": { "BACKEND": "django.core.cache.backends.db.DatabaseCache", "LOCATION": "custom_cache_table", # 自定义缓存表名 "TIMEOUT": 60 * 15, # 对应你原有的15分钟默认缓存超时 "OPTIONS": { "MAX_ENTRIES": 1000, # 你只有1个缓存条目,随便设即可 } } }
配置完成后执行命令生成缓存表:
python manage.py createcachetable
2. 调整视图缓存逻辑(推荐手动缓存,比cache_page更易控制)
原有的cache_page装饰器缓存key和请求路径、请求头强绑定,手动更新时需要计算key比较麻烦,改成手动控制缓存key的逻辑更适合你的场景,修改后的视图代码如下:
from django.core.cache import cache # 固定缓存key,方便后续预更新时直接调用 HOME_ARTICLE_CACHE_KEY = "home_article_list_data" @action(detail=False) def home(self, request) -> Response: # 优先从缓存取数据 cache_data = cache.get(HOME_ARTICLE_CACHE_KEY) if cache_data: return Response(cache_data, headers={'Access-Control-Allow-Origin': '*'}) # 缓存未命中时查库序列化 articles = Article.objects.home() resp_data = serializers.ArticleListSerializer(articles, many=True).data # 写入缓存,超时时间15分钟 cache.set(HOME_ARTICLE_CACHE_KEY, resp_data, settings.DEFAULT_CACHE_TIMEOUT) return Response(resp_data, headers={'Access-Control-Allow-Origin': '*'})
3. 编写自定义Management Command
在你的App目录下新建management/commands目录,目录内新增两个文件:
__init__.py(空文件即可)update_home_article_cache.py,代码如下:
from django.core.management.base import BaseCommand from django.core.cache import cache from yourapp.models import Article from yourapp import serializers # 导入视图里定义的固定缓存key from yourapp.views.article import HOME_ARTICLE_CACHE_KEY from django.conf import settings class Command(BaseCommand): help = "预更新首页文章列表缓存" def handle(self, *args, **options): # 生成最新的序列化数据 articles = Article.objects.home() latest_data = serializers.ArticleListSerializer(articles, many=True).data # 写入缓存覆盖旧数据 cache.set(HOME_ARTICLE_CACHE_KEY, latest_data, settings.DEFAULT_CACHE_TIMEOUT) self.stdout.write(self.style.SUCCESS("首页文章缓存预更新成功"))
注意把代码里的yourapp替换成你实际的App名称。
4. 配置Crontab定时任务
执行crontab -e添加定时任务,每5分钟执行一次缓存更新命令:
# 替换为你实际的虚拟环境路径和项目路径 */5 * * * * /opt/your_project/venv/bin/python /opt/your_project/manage.py update_home_article_cache >> /var/log/update_cache.log 2>&1
注意事项
- 缓存超时时间设为15分钟,定时每5分钟执行一次,就算单次定时任务执行失败,也有10分钟的缓冲时间,不会出现用户访问时缓存击穿的情况
- 数据库缓存对于单条缓存条目性能完全足够,不会有额外负担
- 如果坚持要使用原有的
cache_page装饰器,可通过构造模拟请求对象调用视图,触发cache_page自动写入缓存,只是逻辑复杂度更高
内容的提问来源于stack exchange,提问作者Milano
相关产品推荐
相关产品推荐

