对于现在的动态网站来讲,所有的界面展示都是通过客户端请求服务端,服务端再去请求数据库,然后将请求到的数据渲染后返回给客户端。用户每次访问页面都需要去请求数据库,如果同时有多个人访问的话,对于我们的数据库的压力是相当大的。
所以我们会想,对于不是经常变更的数据,或者不需要实时更新展示的数据,我们可以将数据存放在缓存中,用户下次需要数据的时候,服务端直接从缓存中拿到数据返回给用户即可,不需要每次都去数据库查询,这样会大大降低数据库的压力,提升用户访问速度。
Django提供了多种缓存方法,具体可以参考:https://docs.djangoproject.com/zh-hans/2.1/topics/cache/
下面我们来看看DRF缓存,它对Django的缓存进行了一层封装,使我们用起来更加方便
Django REST Framework中使用缓存,可以使用GitHub上提供的drf-extensions扩展来实现
GitHub地址:https://github.com/chibisov/drf-extensions
参考文档:http://chibisov.github.io/drf-extensions/docs/#caching
drf-extensions 缓存工作原理:
收到用户请求时,会根据请求对应的 view_instance, view_method, request, args, kwargs 等生成一个key,然后通过这个key去内存中查找是否有对应的value,如果有value,将其封装成对应的response返回给客户端
如果通过key没有找到对应的value,则去执行我们的视图函数对应的方法,并将结果作为key值保存在内存中,以便下次使用。
1、安装drf-extensions:pip install drf-extensions
2、使用方法:
首先需要安装 drf-extensions 库:pip install drf-extensions
1)使用装饰器方式
@cache_response
它适用于继承了rest_framework.views.APIView的类,且需要返回一个rest_framework.response.Response的实例
用法如下:
from rest_framework.views import APIView from rest_framework.response import Response from rest_framwork_extensions.cache.decorator import cache_response class GoodListView(APIView): @cache_response() def get(self, request, format=None): goods = Goods.objects.all()[:10] goods_serializer = GoodListSerializer1(goods, many=True) return Response(goods_serializer.data)
第一次访问goods接口,看到使用的时间是1.44s
然后我们再次刷新界面,看到goods接口只是用了259ms
@cache_response()接受4个参数
a)timeout:指定过期时间,单位为秒,即缓存有效期时间。默认为None,即永久缓存,我们也可以在设置文件中修改此参数
REST_FRAMEWORK_EXTENSIONS = {
'DEFAULT_CACHE_RESPONSE_TIMEOUT':60*15 # 即指定有效期为15分钟
}
b)key_func:指定缓存键,默认情况下,每个来自@cache_response装饰器的缓存数据都由key存储,使用DefaultKeyConstructor计算
c)cache:指定装饰器在缓存结果时使用特定的缓存,一般情况下,我们会直接使用默认的default 缓存
d)cache_errors:默认情况下,每个response都会被缓存,包括错误,所以如果我们第一次请求的时候中间出现错误,那么在缓存有效期内,每一次的请求都将会直接将之前缓存的错误信息返回给我们。
我们可以通过修改cache_errors的值为False来改变这种行为。
REST_FRAMEWORK_EXTENSIONS = {
'DEFAULT_CACHE_RESPONSE_TIMEOUT':60*15, # 即指定有效期为15分钟
‘DEFAULT_CACHE_ERRORS’:False
}
2)使用CacheResponseMixin
用于缓存标准视图retrieve和list方法。和viewset搭配使用。
CacheResponseMixin本质上也是使用@Cache_response()装饰器实现,在它的基础上进行了进一步封装,使得使用更加便捷
mixin的示例使用方法:
from rest_framework_extensions.cache.mixins import CacheResponseMixin class GoodListView3(CacheResponseMixin,mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet): queryset = Goods.objects.all().order_by("add_time") serializer_class = GoodListSerializer1 pagination_class = GoodPageView
只需要将CacheResponseMixin加入到我们的试图类函数第一个继承类位置即可。
查看rest_framework_extensions.cache.mixins,可以看到,它下面提供了四个类:
BaseCacheResponseMixin:公共类,只是指定了默认的缓存键功能
ListCacheResponseMixin:继承自BaseCacheResponseMixin,针对list方法缓存
RetrieveCacheResponseMixin:针对retrieve方法缓存
CacheResponseMixin:继承了ListCacheResponseMixin和RetrieveCacheResponseMixin,即既可以对list也可以针对retrieve方法进行缓存。