You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 14:25:29