DRF缓存页面下POST新增文章无法实时显示的解决方案咨询
解决方案
方法1:仅缓存GET类接口(推荐)
你当前把整个ViewSet的dispatch都做了缓存,导致所有请求(包括POST)的响应都被缓存,且列表接口的缓存不会自动更新。正确的做法是只缓存需要的GET方法(list和retrieve),避免缓存写操作接口:
from django.utils.decorators import method_decorator from django.views.decorators.cache import cache_page from django.views.decorators.vary import vary_on_headers from rest_framework import viewsets, permissions, authentication from .serializers import ArticleSerializer class ArticleViewSet(viewsets.ModelViewSet): serializer_class = ArticleSerializer permission_classes = [permissions.IsAuthenticated] authentication_classes = [authentication.TokenAuthentication] # 仅缓存文章列表接口 @method_decorator(cache_page(300)) @method_decorator(vary_on_headers("Authorization",)) def list(self, request, *args, **kwargs): return super().list(request, *args, **kwargs) # 仅缓存单篇文章详情接口 @method_decorator(cache_page(300)) @method_decorator(vary_on_headers("Authorization",)) def retrieve(self, request, *args, **kwargs): return super().retrieve(request, *args, **kwargs)
修改后,POST创建文章的接口不会被缓存,新增成功后,下次请求列表时如果缓存已过期会自动拉取新数据;若缓存未过期,可搭配方法2主动清除缓存。
方法2:新增文章后主动清除列表缓存
如果必须保留dispatch级别的缓存,需要在创建文章成功后,手动清除对应列表接口的缓存:
from django.core.cache import cache from django.utils.cache import generate_cache_key from django.http import HttpRequest from django.utils.decorators import method_decorator from django.views.decorators.cache import cache_page from django.views.decorators.vary import vary_on_headers from rest_framework import viewsets, permissions, authentication from .serializers import ArticleSerializer class ArticleViewSet(viewsets.ModelViewSet): serializer_class = ArticleSerializer permission_classes = [permissions.IsAuthenticated] authentication_classes = [authentication.TokenAuthentication] @method_decorator(cache_page(300)) @method_decorator(vary_on_headers("Authorization",)) def dispatch(self, *args, **kwargs): return super(ArticleViewSet, self).dispatch(*args, **kwargs) def create(self, request, *args, **kwargs): # 执行原有创建逻辑 response = super().create(request, *args, **kwargs) # 生成文章列表接口的缓存key并删除 list_request = HttpRequest() list_request.method = 'GET' # 列表路径默认与create路径一致,若不同需替换为实际路径 list_request.path = request.path list_request.META = request.META.copy() # 携带Authorization头匹配缓存规则 list_request.META['HTTP_AUTHORIZATION'] = request.META.get('HTTP_AUTHORIZATION', '') cache_key = generate_cache_key(list_request, self.dispatch) cache.delete(cache_key) return response
方法3:使用信号清除缓存(适合批量更新场景)
如果有其他方式(如后台管理)修改文章,可通过模型信号自动清除缓存:
from django.db.models.signals import post_save from django.dispatch import receiver from django.core.cache import cache from django.utils.cache import generate_cache_key from django.http import HttpRequest from .models import Article from .views import ArticleViewSet @receiver(post_save, sender=Article) def clear_article_list_cache(sender, instance, **kwargs): # 模拟列表请求生成缓存key request = HttpRequest() request.method = 'GET' request.path = '/api/articles/' # 替换为你的实际列表路径 # 若需区分用户,需补充对应的Authorization头逻辑 cache_key = generate_cache_key(request, ArticleViewSet.as_view({'get': 'list'})) cache.delete(cache_key)
注意:如果是用户专属的文章列表,信号方式需要额外处理不同用户的缓存key,此时方法2的针对性更强。
内容的提问来源于stack exchange,提问作者Abdullah Roshan
相关产品推荐
相关产品推荐

