每天40分玩转Django:Django缓存视图

server/2024/12/23 10:55:59/

Django缓存视图

一、今日学习内容概述

学习模块重要程度主要内容
视图缓存基础⭐⭐⭐⭐⭐缓存装饰器、缓存配置
基于会话缓存⭐⭐⭐⭐⭐会话存储、用户相关缓存
动态缓存处理⭐⭐⭐⭐条件缓存缓存失效
缓存优化策略⭐⭐⭐⭐性能优化、最佳实践

二、缓存配置示例

python"># settings.py
CACHES = {'default': {'BACKEND': 'django.core.cache.backends.redis.RedisCache','LOCATION': 'redis://127.0.0.1:6379/1','OPTIONS': {'CLIENT_CLASS': 'django_redis.client.DefaultClient','PARSER_CLASS': 'redis.connection.HiredisParser','CONNECTION_POOL_CLASS': 'redis.connection.BlockingConnectionPool','CONNECTION_POOL_CLASS_KWARGS': {'max_connections': 50,'timeout': 20,}}},'session': {'BACKEND': 'django.core.cache.backends.redis.RedisCache','LOCATION': 'redis://127.0.0.1:6379/2','TIMEOUT': 86400,  # 1天}
}# 会话引擎配置
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
SESSION_CACHE_ALIAS = 'session'

三、视图缓存实现

3.1 视图装饰器缓存

python"># views.py
from django.views.decorators.cache import cache_page
from django.views.decorators.vary import vary_on_cookie, vary_on_headers
from django.core.cache import cache
from django.shortcuts import render
from .models import Article# 简单的视图缓存
@cache_page(60 * 15)  # 缓存15分钟
def article_list(request):articles = Article.objects.all()return render(request, 'blog/article_list.html', {'articles': articles})# 基于cookie的缓存
@cache_page(60 * 15)
@vary_on_cookie
def user_articles(request):articles = Article.objects.filter(author=request.user)return render(request, 'blog/user_articles.html', {'articles': articles})# 基于请求头的缓存
@cache_page(60 * 15)
@vary_on_headers('User-Agent')
def responsive_view(request):# 根据User-Agent返回不同的模板user_agent = request.META.get('HTTP_USER_AGENT', '')template = 'mobile.html' if 'Mobile' in user_agent else 'desktop.html'return render(request, template)

3.2 高级视图缓存

python">from django.core.cache import cache
from django.conf import settings
from django.utils.cache import get_cache_key
from functools import wraps
import hashlibdef smart_cache_page(timeout=None, cache_key_prefix=None):def decorator(view_func):@wraps(view_func)def wrapper(request, *args, **kwargs):# 生成缓存cache_key = generate_cache_key(request, view_func, args, kwargs)# 尝试从缓存获取响应response = cache.get(cache_key)if response is not None:return response# 执行视图函数response = view_func(request, *args, **kwargs)# 只缓存成功的响应if response.status_code == 200:cache.set(cache_key, response, timeout)return responsereturn wrapperreturn decoratordef generate_cache_key(request, view_func, args, kwargs):# 基础键key_parts = [view_func.__name__,request.path,request.GET.urlencode(),]# 如果是认证用户,添加用户IDif request.user.is_authenticated:key_parts.append(str(request.user.id))# 生成hashkey = hashlib.md5(''.join(key_parts).encode()).hexdigest()return f'view_cache_{key}'# 使用示例
@smart_cache_page(timeout=300)  # 5分钟缓存
def article_detail(request, article_id):article = Article.objects.get(id=article_id)return render(request, 'blog/article_detail.html', {'article': article})

3.3 基于会话的缓存管理器

python"># cache_managers.py
from django.core.cache import caches
from django.conf import settings
import jsonclass SessionCacheManager:def __init__(self, session_key):self.session_key = session_keyself.cache = caches['session']def _get_user_cache_key(self, key):"""生成用户特定的缓存键"""return f'session_{self.session_key}_{key}'def get(self, key, default=None):"""获取缓存数据"""cache_key = self._get_user_cache_key(key)value = self.cache.get(cache_key)return json.loads(value) if value else defaultdef set(self, key, value, timeout=None):"""设置缓存数据"""cache_key = self._get_user_cache_key(key)self.cache.set(cache_key, json.dumps(value), timeout)def delete(self, key):"""删除缓存数据"""cache_key = self._get_user_cache_key(key)self.cache.delete(cache_key)def clear_all(self):"""清除该会话的所有缓存"""pattern = f'session_{self.session_key}_*'self.cache.delete_pattern(pattern)# 使用中间件自动处理会话缓存
class SessionCacheMiddleware:def __init__(self, get_response):self.get_response = get_responsedef __call__(self, request):# 为请求添加缓存管理器request.cache_manager = SessionCacheManager(request.session.session_key)response = self.get_response(request)return response

四、缓存流程图

在这里插入图片描述

五、实际应用示例

5.1 商品列表缓存

python"># views.py
from django.views.decorators.cache import cache_page
from django.core.cache import cache
from .models import Productclass ProductListView:def get_products(self, category=None, page=1):# 生成缓存cache_key = f'products_list_{category}_{page}'products = cache.get(cache_key)if products is None:# 查询数据库queryset = Product.objects.all()if category:queryset = queryset.filter(category=category)# 分页paginator = Paginator(queryset, 20)products = paginator.get_page(page)# 缓存结果cache.set(cache_key, products, 300)  # 5分钟缓存return products@cache_page(60 * 5)def list_view(self, request):category = request.GET.get('category')page = request.GET.get('page', 1)products = self.get_products(category, page)return render(request, 'shop/product_list.html', {'products': products})

5.2 用户购物车缓存

python"># cart.py
class CartManager:def __init__(self, request):self.session_key = request.session.session_keyself.cache = caches['session']def get_cart_key(self):return f'cart_{self.session_key}'def get_cart(self):return self.cache.get(self.get_cart_key()) or {}def add_item(self, product_id, quantity=1):cart = self.get_cart()product_id = str(product_id)if product_id in cart:cart[product_id]['quantity'] += quantityelse:cart[product_id] = {'quantity': quantity,'added_at': datetime.now().isoformat()}self.cache.set(self.get_cart_key(), cart, 86400)  # 1天def remove_item(self, product_id):cart = self.get_cart()product_id = str(product_id)if product_id in cart:del cart[product_id]self.cache.set(self.get_cart_key(), cart)def clear(self):self.cache.delete(self.get_cart_key())

六、性能优化建议

  1. 缓存键设计

    • 使用有意义的前缀
    • 避免过长的键名
    • 包含版本信息
  2. 缓存粒度控制

    • 合理设置过期时间
    • 避免过度缓存
    • 考虑缓存成本
  3. 缓存更新策略

    • 主动更新
    • 被动失效
    • 版本控制
  4. 缓存监控

    • 命中率统计
    • 内存使用监控
    • 性能分析

七、测试用例

python"># tests.py
from django.test import TestCase, Client
from django.core.cache import cache
from django.urls import reverseclass ViewCacheTests(TestCase):def setUp(self):self.client = Client()cache.clear()def test_cached_view(self):# 第一次请求response1 = self.client.get(reverse('article_list'))content1 = response1.content# 修改数据Article.objects.create(title='Test Article')# 第二次请求应该返回缓存的内容response2 = self.client.get(reverse('article_list'))content2 = response2.contentself.assertEqual(content1, content2)

八、常见问题和解决方案

  1. 缓存穿透
python">def get_data(self, key):# 使用空值标记value = cache.get(key)if value is None:data = expensive_operation()if data is None:# 缓存空值,避免频繁查询cache.set(key, 'NULL', 300)else:cache.set(key, data)return datareturn None if value == 'NULL' else value
  1. 缓存雪崩
python">import randomdef set_with_jitter(key, value, timeout):"""添加随机过期时间,避免同时失效"""jitter = random.randint(-60, 60)final_timeout = timeout + jittercache.set(key, value, final_timeout)
  1. 缓存一致性
python">def update_data(self, key, value):"""先更新数据库,再删除缓存"""try:# 更新数据库self.model.objects.filter(pk=key).update(value=value)# 删除缓存cache.delete(f'data_{key}')except Exception as e:# 记录错误,可能需要后续处理logger.error(f'Failed to update data: {e}')

九、总结

通过本章学习,你应该掌握:

  1. Django视图缓存的基本使用
  2. 会话缓存的实现方法
  3. 缓存性能优化策略
  4. 常见缓存问题的解决方案

怎么样今天的内容还满意吗?再次感谢朋友们的观看,关注GZH:凡人的AI工具箱,回复666,送您价值199的AI大礼包。最后,祝您早日实现财务自由,还请给个赞,谢谢!


http://www.ppmy.cn/server/152471.html

相关文章

中软高科身份证云解码金融(银行)解决方案介绍

多年来,中软高科一直深耕身份证云解码领域,对身份证云解码应用于金融(银行),进行了大量且深入的研究。从长期调研来看,金融(银行)的痛点需求主要有: 传统身份证解码设备…

一篇文章掌握WebService服务、工作原理、核心组件、主流框架

目录 1、WebService定义 解决问题: 2、WebService的工作原理 2.1 实现一个完整的Web服务包括以下步骤 2.2 调用方式 3、Web Service的核心组件 3.1 XML 3.2 SOAP 3.3 WSDL 3.4 UDDI 4、主流框架 4.1 AXIS(已淘汰) 4.2 XFire 4.3 CXF 5、Soap协议详解…

Farfalle - 开源的AI搜索引擎

2600 Stars 232 Forks 32 Issues 4 贡献者 Apache-2.0 License Python 语言 代码: https://github.com/rashadphz/farfalle 主页: Farfalle 演示: Farfalle 更多AI开源软件:https://www.aiinn.cn/sources FarFalle 是一款开源的AI搜索引擎项目,类似Perpl…

AI Agent案例全解析:百度营销智能体(8/30)

引言:在当今这个科技飞速发展的时代,AI技术呈现出爆发式的增长,正以前所未有的态势改变着众多行业的发展轨迹,营销领域也不例外。随着市场竞争的日益激烈,传统营销模式逐渐显露出疲态,对于变革的需求愈发迫…

Golang 的并发优势

在如今的编程领域,一个程序能够同时处理多个任务的能力非常重要,这就是所谓的并发处理。而 Golang 在并发编程方面表现十分出色,具有很多独特的优势,简直不要太简单。 一、轻量级的协程(Goroutine) 在传统…

JUC并发同步工具在大厂中应用实战

常用并发同步工具类的真实应用场景 jdk提供了比synchronized更加高级的各种同步工具,包括ReentrantLock、Semaphore、CountDownLatch、CyclicBarrier等,可以实现更加丰富的多线程操作。 https://www.processon.com/view/link/6620b9d763dc8148f6486eda…

一起学Git【第四节:添加和提交文件】

通过前三节的学习,基本上对Git有了初步的了解,下面开始进行文件的添加和提交的流程。 这里主要涉及四个命令: git init 创建仓库git status查看仓库状态git add添加至暂存区git commit提交文件之前已经使用过git init命令了,此处不再具体讲解。参照一起学Git【第二节:创建…

Linux常用脚本(七) ---简单防火墙管理

#!/bin/bash# 检查是否以 root 权限运行 if [ "$(id -u)" -ne 0 ]; thenecho "请使用 root 权限运行此脚本"exit 1 fi# 用法 usage() {echo "用法: $0 {start|stop|status|flush}"echo " start : 启动防火墙并设置基本规则"echo &qu…