DRF中使用cache_page时,同路由下如何刷新缓存获取最新数据?
解决Django缓存信息流后发布帖子实时刷新的最优方案
当前通过URL参数绕过缓存的方式虽然能临时解决问题,但存在不够优雅、会生成冗余缓存键的问题。以下是几个更适配业务场景的优化方案:
方案1:手动清除目标缓存键
利用Django提供的工具,在用户发布帖子的瞬间,直接删除帖子列表页面的缓存键,这样下一次请求就会重新生成包含新帖子的缓存。
实现细节:
- 从
django.utils.cache导入get_cache_key,用来生成和cache_page一致的缓存键 - 在发布帖子的视图中,构造帖子列表的请求对象,获取对应缓存键并删除
# 发布帖子的视图函数/类视图方法 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装饰器,改用视图内的逻辑控制:对刚发布帖子的用户直接返回实时数据,其他用户仍走缓存。
实现细节:
- 在发布帖子时,用session记录用户的最近发布时间
- 在帖子列表视图中,判断用户是否刚发布过帖子,决定是否走缓存
# 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:缓存版本控制
给帖子列表的缓存设置版本号,发布帖子时递增版本号,旧版本缓存自动失效,用户请求会获取新的缓存数据。
实现细节:
- 用一个全局键存储缓存版本号
- 自定义
cache_page的版本参数,动态获取当前版本 - 发布帖子时更新版本号
# 定义全局缓存版本键 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,发布帖子后只清除当前用户的缓存,不影响其他用户。
实现细节:
- 去掉
urls.py中的cache_page装饰器,在视图内手动处理缓存 - 缓存键包含用户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
相关产品推荐
相关产品推荐

