Django类视图缓存绑定GET参数的API响应报ContentNotRenderedError如何解决
问题原因
你遇到的报错本质是DRF返回的Response对象在未渲染的状态下无法被pickle序列化存入缓存,必须先完成内容渲染才能被缓存存储。
解决方案
方案1:最小改动:主动渲染响应后缓存
只需要在存入缓存前调用响应的render()方法即可,修改后代码如下:
class ProductsListCreate(generics.ListCreateAPIView): def list(self, request, *args, **kwargs): producent = request.query_params.get("producent") cache_key = f"response-products-{producent}" cached_response = cache.get(cache_key, None) if not cached_response: queryset = self.filter_queryset(self.get_queryset()) page = self.paginate_queryset(queryset) serializer = self.get_serializer(page) response = self.get_paginated_response(serializer.data) # 新增一行:主动渲染响应内容 response.render() cache.set(cache_key, response, timeout=20) return response return cached_response
方案2:更灵活的实现:缓存结构化数据而非响应对象
直接缓存序列化后的数据和分页元信息,避免对响应对象做序列化,缓存占用空间更小,后续修改响应格式也更方便:
class ProductsListCreate(generics.ListCreateAPIView): def list(self, request, *args, **kwargs): producent = request.query_params.get("producent") cache_key = f"product-data-{producent}" cached_data = cache.get(cache_key, None) if not cached_data: queryset = self.filter_queryset(self.get_queryset()) page = self.paginate_queryset(queryset) serializer = self.get_serializer(page) # 直接存分页后的结构化数据 cached_data = self.get_paginated_response(serializer.data).data cache.set(cache_key, cached_data, timeout=20) return Response(cached_data)
注意事项
- 缓存键需要覆盖所有影响返回结果的变量:如果接口除了
producent外还有其他过滤参数、或者需要按用户权限返回不同内容,需要把对应的参数、用户ID等信息加入缓存键,避免返回错误的缓存数据。 - 如果你后续想复用
cache_page装饰器的能力,可以自定义缓存键生成函数,同样可以实现按请求参数动态生成缓存键的需求,不需要手动编写缓存读写逻辑。
内容的提问来源于stack exchange,提问作者Beorn
相关产品推荐
相关产品推荐

