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

DRF中使用cache_page时,同路由下如何刷新缓存获取最新数据?

解决Django缓存信息流后发布帖子实时刷新的最优方案

当前通过URL参数绕过缓存的方式虽然能临时解决问题,但存在不够优雅、会生成冗余缓存键的问题。以下是几个更适配业务场景的优化方案:

方案1:手动清除目标缓存键

利用Django提供的工具,在用户发布帖子的瞬间,直接删除帖子列表页面的缓存键,这样下一次请求就会重新生成包含新帖子的缓存。

实现细节:

  1. 从django.utils.cache导入get_cache_key,用来生成和cache_page一致的缓存键
  2. 在发布帖子的视图中,构造帖子列表的请求对象,获取对应缓存键并删除
# 发布帖子的视图函数/类视图方法
from django.utils.cache import get_cache_key
from django.core.cache import cache
from django.http import HttpRequest

def create_post(request):
    # 处理帖子发布的业务逻辑...
    
    # 构造帖子列表接口的请求对象
    list_request = HttpRequest()
    list_request.method = 'GET'
    list_request.path = '/v1/posts/'  # 对应你的帖子列表路由路径
    # 如果视图依赖用户认证,记得设置用户对象
    if request.user.is_authenticated:
        list_request.user = request.user
    
    try:
        # 获取缓存键并删除
        cache_key = get_cache_key(list_request)
        cache.delete(cache_key)
    except Exception:
        # 缓存键不存在时直接忽略,不影响业务
        pass
    
    return Response({"status": "success"})

方案2:条件化缓存(针对发布用户跳过缓存)

放弃全局的cache_page装饰器,改用视图内的逻辑控制:对刚发布帖子的用户直接返回实时数据,其他用户仍走缓存。

实现细节:

  1. 在发布帖子时,用session记录用户的最近发布时间
  2. 在帖子列表视图中,判断用户是否刚发布过帖子,决定是否走缓存
# views.py
import time
from django.core.cache import cache
from rest_framework.views import APIView

class PostListAPIView(APIView):
    def get(self, request):
        # 检查用户最近发布时间(1分钟内发布过则返回实时数据)
        last_post_time = request.session.get('last_post_time', 0)
        if time.time() - last_post_time < 60:
            # 直接查询数据库返回最新数据
            posts = Post.objects.all().order_by('-created_at')
            serializer = PostSerializer(posts, many=True)
            return Response(serializer.data)
        
        # 其他情况走缓存逻辑
        cache_key = f"post_list_{request.user.id}" if request.user.is_authenticated else "post_list_anonymous"
        posts = cache.get(cache_key)
        if not posts:
            posts = Post.objects.all().order_by('-created_at')
            cache.set(cache_key, posts, 60*10)
        
        serializer = PostSerializer(posts, many=True)
        return Response(serializer.data)

# 发布帖子的视图中记录时间
def create_post(request):
    # 处理发布逻辑...
    request.session['last_post_time'] = time.time()
    return Response({"status": "success"})

方案3:缓存版本控制

给帖子列表的缓存设置版本号,发布帖子时递增版本号,旧版本缓存自动失效,用户请求会获取新的缓存数据。

实现细节:

  1. 用一个全局键存储缓存版本号
  2. 自定义cache_page的版本参数,动态获取当前版本
  3. 发布帖子时更新版本号
# 定义全局缓存版本键
POST_LIST_CACHE_VERSION_KEY = "post_list_cache_version"

# views.py
from django.core.cache import cache
from django.views.decorators.cache import cache_page
from django.utils.decorators import method_decorator

def get_post_list_version():
    return cache.get(POST_LIST_CACHE_VERSION_KEY, 1)

# 用带版本的缓存装饰器
@method_decorator(
    cache_page(60*10, key_prefix='post_list', version=get_post_list_version), 
    name='get'
)
class PostListAPIView(APIView):
    def get(self, request):
        posts = Post.objects.all().order_by('-created_at')
        serializer = PostSerializer(posts, many=True)
        return Response(serializer.data)

# 发布帖子时更新版本号
def create_post(request):
    # 处理发布逻辑...
    current_version = cache.get(POST_LIST_CACHE_VERSION_KEY, 1)
    cache.set(POST_LIST_CACHE_VERSION_KEY, current_version + 1)
    return Response({"status": "success"})

方案4:个性化缓存(针对用户专属信息流)

如果你的信息流是用户个性化的(比如只展示关注用户的帖子),可以给每个用户的缓存键加上用户ID,发布帖子后只清除当前用户的缓存,不影响其他用户。

实现细节:

  1. 去掉urls.py中的cache_page装饰器,在视图内手动处理缓存
  2. 缓存键包含用户ID,发布帖子时只删除当前用户的缓存键
# urls.py
urlpatterns = [
    path('', views.PostListAPIView.as_view(), name="post-list")
]

# views.py
from django.core.cache import cache

class PostListAPIView(APIView):
    def get(self, request):
        # 生成带用户ID的缓存键
        if request.user.is_authenticated:
            cache_key = f"post_list_user_{request.user.id}"
            # 个性化查询:只取关注用户的帖子
            posts_queryset = Post.objects.filter(author__in=request.user.following.all())
        else:
            cache_key = "post_list_anonymous"
            posts_queryset = Post.objects.all()
        
        posts = cache.get(cache_key)
        if not posts:
            posts = posts_queryset.order_by('-created_at')
            cache.set(cache_key, posts, 60*10)
        
        serializer = PostSerializer(posts, many=True)
        return Response(serializer.data)

# 发布帖子的视图中清除当前用户缓存
def create_post(request):
    # 处理发布逻辑...
    if request.user.is_authenticated:
        cache_key = f"post_list_user_{request.user.id}"
        cache.delete(cache_key)
        # 可选:如果需要让关注该用户的人看到新帖子,可遍历关注者并删除他们的缓存(注意性能成本)
    return Response({"status": "success"})

内容的提问来源于stack exchange,提问作者Muhammad Talha Abbas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 09:05:27