Django REST Framework: 使用cach_page和drf-extensions进行缓存
对于经常被查询使用而且不怎么变化的数据, 建议对Django REST Framework(DRF)的响应数据进行缓存, 这样可以避免重复数据库查询, 大大加快响应时间。DRF支持两种数据缓存方式: 1. Django的原生cache_page装饰器; 2. drf-extensions这个第三方库。
方法1. 原生cache_page装饰器
使用Django提供的method_decorator装饰器,可以将普通装饰器比如cache_page应用于类视图里。cache_page可以指定缓存时间(单位秒)。
from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_page
from django.views.decorators.vary import vary_on_cookie, vary_on_headers
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework import viewsets
class UserViewSet(viewsets.ViewSet):
# With cookie: cache requested url for each user for 2 hours
@method_decorator(cache_page(60*60*2))
@method_decorator(vary_on_cookie)
def list(self, request, format=None):
content = {
'user_feed': request.user.get_user_feed()
}
return Response(content)
class ProfileView(APIView):
# With auth: cache requested url for each user for 2 hours
@method_decorator(cache_page(60*60*2))
@method_decorator(vary_on_headers("Authorization",))
def get(self, request, format=None):
content = {
'user_feed': request.user.get_user_feed()
}
return Response(content)
class PostView(APIView):
# 缓存特定请求url地址的数据
@method_decorator(cache_page(60*60*2))
def get(self, request, format=None):
content = {
'title': 'Post title',
'body': 'Post content'
}
return Response(content)
注意:cache_page只能缓存GET和HEAD请求,并返回200的状态码。
方法2. 使用drf-extensions第三方库
1. pip安装
pip install drf-extensions
2. 直接添加cache_response装饰器
drf-extensions提供的cache_response装饰器可以直接应用于get方法上,而无需使用method_decorator进行转换。
from rest_framework_extensions.cache.decorators import cache_response
class UserView(views.APIView):
@cache_response()
def get(self, request, *args, **kwargs):
...
cache_response装饰器可以接收两个参数, 一个为缓存时间,一个为默认缓存后端名字,如下所示:
@cache_response(timeout=60*60, cache='default')
如果不设置参数,可以在settings.py进行默认配置:
# settings.py
# DRF扩展
REST_FRAMEWORK_EXTENSIONS = {
# 默认缓存时间
'DEFAULT_CACHE_RESPONSE_TIMEOUT': 60 * 60,
# 缓存存储
'DEFAULT_USE_CACHE': 'default',
}
注意,cache_response装饰器既可以装饰在类视图中的get方法上,也可以装饰在REST framework扩展类提供的list或retrieve方法上。
3. 使用drf-extensions提供的扩展类
drf-extensions还提供了如下3个常用的扩展Mixin类,位于rest_framework_extensions.cache.mixins中。
ListCacheResponseMixin
用于缓存返回列表数据的视图,与ListModelMixin扩展类配合使用,实际是为list方法添加了cache_response装饰器
RetrieveCacheResponseMixin
用于缓存返回单一数据的视图,与RetrieveModelMixin扩展类配合使用,实际是为retrieve方法添加了cache_response装饰器
CacheResponseMixin
为视图集同时补充List和Retrieve两种缓存,与ListModelMixin和RetrieveModelMixin一起配合使用。
最常用的是CacheResponseMixin,它对单个对象或对象列表都进行缓存,使用示例如下所示:
from myapps.serializers import UserSerializer
from rest_framework_extensions.cache.mixins import CacheResponseMixin
class UserViewSet(CacheResponseMixin, viewsets.ModelViewSet):
serializer_class = UserSerializer
小结
Django REST Framework(DRF)提供了2种对经常查询使用却又不怎么变化的响应数据进行缓存的方法: 1. Django的原生cache_page装饰器; 2. drf-extensions这个第三方库。个人优先推荐drf-extensions提供的CacheResponseMixin这个Mixin类。