DRF 缓存策略 #
一、缓存概述 #
1.1 缓存类型 #
| 类型 | 说明 |
|---|---|
| 视图缓存 | 缓存整个视图响应 |
| 数据缓存 | 缓存数据库查询结果 |
| HTTP缓存 | 利用浏览器缓存 |
1.2 Django缓存配置 #
python
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.redis.RedisCache',
'LOCATION': 'redis://127.0.0.1:6379/1',
}
}
二、视图缓存 #
2.1 使用装饰器 #
python
from django.views.decorators.cache import cache_page
from django.utils.decorators import method_decorator
class ArticleViewSet(viewsets.ModelViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
@method_decorator(cache_page(60 * 5))
def list(self, request, *args, **kwargs):
return super().list(request, *args, **kwargs)
@method_decorator(cache_page(60 * 10))
def retrieve(self, request, *args, **kwargs):
return super().retrieve(request, *args, **kwargs)
2.2 缓存键 #
python
from django.views.decorators.vary import vary_on_headers
class ArticleViewSet(viewsets.ModelViewSet):
@method_decorator(cache_page(60 * 5))
@method_decorator(vary_on_headers('Authorization'))
def list(self, request, *args, **kwargs):
return super().list(request, *args, **kwargs)
三、数据缓存 #
3.1 查询集缓存 #
python
from django.core.cache import cache
class ArticleViewSet(viewsets.ModelViewSet):
def get_queryset(self):
cache_key = 'articles_list'
queryset = cache.get(cache_key)
if queryset is None:
queryset = Article.objects.select_related('author', 'category')
cache.set(cache_key, queryset, 60 * 5)
return queryset
3.2 序列化数据缓存 #
python
class ArticleViewSet(viewsets.ModelViewSet):
def list(self, request, *args, **kwargs):
cache_key = f'articles_list_{request.query_params.urlencode()}'
data = cache.get(cache_key)
if data is None:
queryset = self.filter_queryset(self.get_queryset())
serializer = self.get_serializer(queryset, many=True)
data = serializer.data
cache.set(cache_key, data, 60 * 5)
return Response(data)
四、HTTP缓存 #
4.1 ETag #
python
from django.views.decorators.http import condition
def article_etag(request, *args, **kwargs):
article = Article.objects.get(pk=kwargs['pk'])
return f'"{article.updated_at.timestamp()}"'
class ArticleDetailView(APIView):
@condition(etag_func=article_etag)
def get(self, request, pk):
article = get_object_or_404(Article, pk=pk)
serializer = ArticleSerializer(article)
return Response(serializer.data)
4.2 Last-Modified #
python
def article_last_modified(request, *args, **kwargs):
article = Article.objects.get(pk=kwargs['pk'])
return article.updated_at
class ArticleDetailView(APIView):
@condition(last_modified_func=article_last_modified)
def get(self, request, pk):
article = get_object_or_404(Article, pk=pk)
serializer = ArticleSerializer(article)
return Response(serializer.data)
4.3 Cache-Control #
python
class ArticleViewSet(viewsets.ModelViewSet):
def list(self, request, *args, **kwargs):
response = super().list(request, *args, **kwargs)
response['Cache-Control'] = 'max-age=300'
return response
五、缓存失效 #
5.1 信号触发 #
python
from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver
from django.core.cache import cache
@receiver(post_save, sender=Article)
@receiver(post_delete, sender=Article)
def invalidate_article_cache(sender, instance, **kwargs):
cache.delete('articles_list')
cache.delete(f'article_{instance.id}')
5.2 手动清除 #
python
class ArticleViewSet(viewsets.ModelViewSet):
def perform_create(self, serializer):
instance = serializer.save()
cache.delete('articles_list')
return instance
def perform_update(self, serializer):
instance = serializer.save()
cache.delete('articles_list')
cache.delete(f'article_{instance.id}')
return instance
六、总结 #
本章学习了DRF缓存策略:
- 视图缓存:缓存整个响应
- 数据缓存:缓存查询结果
- HTTP缓存:利用浏览器缓存
- 缓存失效:自动和手动清除
缓存是提升API性能的重要手段!
最后更新:2026-03-28