【django开发手册】DRF自动缓存应用实践分享——缓存注解详解及实现原理

news/2025/1/15 17:17:35/

本文节选自笔者博客:https://www.blog.zeeland.cn/archives/23r9oiasaaa

  • 💖 作者简介:大家好,我是Zeeland,全栈领域优质创作者。
  • 📝 CSDN主页:Zeeland🔥
  • 📣 我的博客:Zeeland
  • 📚 Github主页: Undertone0809 (Zeeland) (github.com)
  • 🎉 支持我:点赞👍+收藏⭐️+留言📝
  • 📣 系列专栏:django开发手册🍁
  • 💬介绍:The mixture of software dev+Iot+ml+anything🔥

Django系列专栏

  • 【django开发手册】Django 中使用自定义用户模型:一个比自带 User 更强的选择
  • 【django开发手册】如何使用select_related进行一次连表查询
  • 【django开发手册】drf通过添加自定义字段优化DRF序列化器,轻松实现高速API
  • 【django开发手册】解决admin添加外键下拉显示外键的问题
  • 【Django Rest Framework优化实践】ResponseResult、异常处理方法详解
  • 【DRF】深度分析枚举类型在DRF中的序列化问题及解决方案
  • 【django开发手册】关于django admin添加表信息的时候外键无法为空的问题解决方案
  • 【django开发手册】django admin如何显示外键对应的字段
  • 【django开发手册】DRF外键模型查询没有信息?教你实现序列化返回

前言

Web应用性能是非常重要的,用户访问速度和响应时间会直接影响到用户体验。对于一个需要经常访问、更新的Web应用,缓存机制是非常重要的,它可以避免频繁的数据库访问,提高网站的访问速度、降低服务器负载。本文会探讨以下几个问题:

  • 如何使用DRF自动缓存来优化API性能?以及如何解决常见的缓存问题。
  • django cache_page和 drf cache_response的区别?
  • 缓存的更新机制

Django cache

首先,django也提供了其cache机制,通过from django.views.decorators.cache import cache_page引入cache_page就可以进行使用了,使用方法如下所示:

from django.views.decorators.cache import cache_page@cache_page(60 * 15)
def my_view(request):...

当你第一次调用这个接口的时候,django会为这个接口创建一个60*15秒的缓存,当你后面再去访问的时候,访问速度就会快很多。

需要注意的是,你需要考虑缓存的刷新机制, 一般情况下,缓存不会自动刷新,你需要自己去手动更新,可以说这是一个弊端。

下面的demo是一个将cache_page结合drf的ModelViewSet一起使用,其作用也是接口数据的缓存。

class MeasuringPointViewSet(viewsets.ModelViewSet):queryset = models.MeasuringPoint.objects.all().order_by('mpoint_id')serializer_class = MeasuringPointSerializer@method_decorator(cache_page(60 * 60))def list(self, request, *args, **kwargs):"""根据项目获取所有测点"""project_id = request.query_params.get('project_id')queryset = self.get_queryset().filter(project_id=project_id)serializer = self.get_serializer(results, many=True)return paginator.get_paginated_response(serializer.data)

DRF cache

对于上面提到的缓存刷新问题,可以使用DRF自带的缓存方法进行数据更新时的自动清除。

快速上手

  1. 导包,因为drf cache属于其扩展功能,因此需要单独安装drf的扩展库
pip install drf-extensions
  1. views.py 中引入缓存类:
from rest_framework_extensions.cache.decorators import cache_response
  1. 替换@method_decorator(cache_page(60 * 60))@cache_response(key_func='get_cache_key'),并添加get_cache_key函数:
class MeasuringPointViewSet(viewsets.ModelViewSet):queryset = models.MeasuringPoint.objects.all().order_by('mpoint_id')serializer_class = MeasuringPointSerializer@staticmethoddef get_cache_key(request, *args, **kwargs):project_id = request.query_params.get('project_id')return f'{request.path}?project_id={project_id}'@cache_response(key_func='get_cache_key')def list(self, request, *args, **kwargs):"""根据项目获取所有测点"""paginator = CustomPagination()project_id = request.query_params.get('project_id')queryset = self.get_queryset().filter(project_id=project_id)results = paginator.paginate_queryset(queryset, request)serializer = self.get_serializer(results, many=True)return paginator.get_paginated_response(serializer.data)

这里的get_cache_key函数根据请求的URL和参数构建出缓存的Key值,以避免不同参数的请求缓存混淆。

现在每次数据更新时,DRF会自动清除缓存,确保获取到的数据是最新的。

cache_response和cache_page的区别?

@cache_response@cache_page都是DRF提供的用来缓存视图函数返回结果的装饰器,它们之间的区别在于缓存的级别以及缓存使用的位置不同。

@cache_response缓存的是响应的结果,因此对于同一个请求,如果响应内容不同,那么它们的缓存结果也会不同。而@cache_page则是缓存的整个页面,因此无论响应内容是否相同,对于同一个请求,它们的缓存结果是相同的。

另外,@cache_response是一个更加细粒度的缓存策略,因为它只缓存了响应,这样可以避免将不同的请求的数据混在一起。而@cache_page则是更加粗粒度的缓存策略,由于缓存了整个页面,因此会引发数据混淆的问题,需要对缓存的内容和键做更严格的控制。

因此,一般情况下,我们会优先选择使用@cache_response来缓存响应结果,以避免数据混淆的问题。

什么时候cache_response会更新缓存?缓存时间有多久?还是需要自己手动更新缓存?

@cache_response的缓存持续时间是由DRF的缓存系统设置的,默认情况下,它会将缓存时间设置为None,也就是永久缓存。但是,当使用@cache_response来缓存响应结果时,当以下任意情况出现时,缓存都会自动更新:

  1. 通过PUT、PATCH、POST或DELETE请求更新了资源;
  2. 其他视图调用了与当前视图相同的缓存键(例如,当一个有关联的资源被添加、修改或删除时);
  3. 从缓存中读取的数据已经过期。

这些情况会触发DRF的自动缓存失效机制,它会在从缓存中获取响应结果时,先检查该缓存是否仍然有效,如果已经失效,则会调用视图函数来生成新的响应,并且更新缓存。

需要注意的是,如果你的业务需要,你也可以手动清除缓存。可以使用类似于cache.delete('cache_key')这样的代码来手动删除指定缓存键的缓存。

注意事项

  • 不管你使用cache_page还是cache_response,你都需要注意缓存刷新的问题。
  • 如果你使用了django自带的admin管理系统,当你在后台修改数据的时候,使用cache_response也是无法自动刷新数据的,因为django自带的管理系统是直接修改数据库中的数据,并不会触发cache_response的缓存更新机制,这一点一定要注意一下。所以如果你有精力,对于每一个接口你都可以编写其缓存逻辑,但是更有性价比的方案是,对于那些实在不经常更新的数据,你可以使用缓存,而对于经常更新的数据,你可以把缓存时间设置小一点。

总结

本文主要讨论DRF自动缓存的使用。我们首先介绍了如何使用@cache_response装饰器来缓存视图函数的响应结果。这个装饰器可以提供细粒度的缓存控制,能够避免不同请求的数据混淆问题。我们还介绍了如何通过get_cache_key函数来生成唯一的缓存键,以便于管理和查询。

DRF自动缓存机制是一个非常有用的工具,可以帮助我们优化API性能,提高Web应用的访问速度和响应时间。通过使用@cache_response装饰器和get_cache_key函数,我们可以实现细粒度的缓存控制,避免数据混淆问题。同时,DRF的自动缓存失效机制可以自动清除缓存,避免数据不一致的问题。


http://www.ppmy.cn/news/62943.html

相关文章

改进YOLOv8 | 即插即用篇 | CVPR2023最新注意力 | 《BiFormer:视觉变换器与双层路由注意力》

作为视觉变换器的核心构建模块,注意力是一种强大的工具,可以捕捉长程依赖关系。然而,这种强大的功能付出了代价:计算负担和内存占用巨大,因为需要在所有空间位置上计算成对的令牌交互。一系列的研究尝试通过引入手工制作和与内容无关的稀疏性来缓解这个问题,例如将注意力…

rk3568 系统移植和编译

1。 硬件问题 尽量根据原版 evb 开发版 pcb 进行布线和移植,切记不可自行走线。 emmc 和 ddr4 选型都有要求的,按照硬件手册进行设计 2。软件问题 2.1 目前固件系统选用1.3.2 版本进行设计 解压后运行 .repo/repo/repo sync -c 更新代码 2.2 ubo…

用 Bitmap 实现亿级海量数据统计

在移动应用的业务场景中,我们需要保存这样的信息:一个 key 关联了一个数据集合。 常见的场景如下: 给一个 userId ,判断用户登陆状态; 显示用户某个月的签到次数和首次签到时间; 两亿用户最近 7 天的签到…

PS VR创始成员:瑕不掩瑜,PS VR2是跨世代的飞跃

今年2月,索尼次世代VR头显PS VR2正式发售,这款立项近7年的产品受到了游戏玩家和从业者广泛关注,市面上也有很多种不同的测评报告。PS VR项目创始成员、前索尼沉浸式体验专家、高级VR游戏设计师Jed Ashforth也发表了自己对于该头显的一些看法&…

放弃40k月薪的程序员工作,选择公务员,我来分享一下看法

我有一个朋友,拒绝了我为他提供的4万薪水的工作,去了一个体制内的银行,做程序员,即使薪水减半。他之前在北京一家大公司做程序员,一个月30k。当我开始创业时,我拉他来和我一起干,但那时我们太小…

Accesss数据库的那点事

Accesss数据库的那点事 1.Access的简介 Access(全称为Microsoft Access)是一个关系型数据库管理系统(RDBMS)。它是由微软公司开发的数据库软件,用于创建、管理和操作数据库应用程序。 Access提供了一个可视化的开发环…

Spring MVC框架

Spring MVC框架 Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。使用 Spring 可插入的 MVC 架构,从而在使用Spring进行WEB开发时,可以选择使用Spring的Spri…

ProbTransformer:应对RNA折叠等自然过程数据模糊的神秘力量

编译 | 于洲‍ 今天我们介绍来自德国弗赖堡大学计算机科学系的Jrg K.H. Franke, Frederic Runge以及Frank Hutter发表在NeurIPS 2022会议上的工作,该文章介绍了一种新颖的基于概率的神经网络架构ProbTransformer,它是Transformer生态系统的一种层级增强&…