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