DRF Spectacular错误响应示例被分页结构包裹,如何解决?
问题
我为ArchiveListView的GET接口配置了两种响应:
- 200状态返回分页列表(使用
ArchiveListViewSerializer) - 400状态返回错误信息(使用
ExceptionSerializer)
期望400的响应示例为:
{ "api_status_code": "DATE_PARSE_ERROR", "extra": { "details": "asdf" } }
但Swagger UI及生成的OpenAPI文档中,该示例被分页结构(包含count、next、previous、results)错误包裹,生成的OpenAPI片段显示示例被嵌套在results中,不过响应Schema是正确指向Exception的。
相关实现代码如下:
class ExceptionSerializer(serializers.Serializer): api_status_code = serializers.CharField() extra = serializers.DictField(required=False) @extend_schema_view( get=extend_schema( responses={ 200: OpenApiResponse( response=s.ArchiveListViewSerializer, examples=[], ), 400: OpenApiResponse( response=ExceptionSerializer, examples=[ OpenApiExample( "DATE_PARSE_ERROR", value={"api_status_code": "DATE_PARSE_ERROR", "extra": {"details": "asdf"}}, status_codes=[400], response_only=True, ) ], ), }, ) ) class ArchiveListView(LoginRequiredMixin, ListAPIView): model = m.Archive serializer_class = s.ArchiveListViewSerializer pagination_class = LimitOffsetPagination
解决方案
问题根源在于ListAPIView默认启用分页逻辑,drf-spectacular会自动为List视图的响应添加分页包装,即使你为400状态指定了非分页的ExceptionSerializer,框架仍可能错误套用分页结构。
可以通过以下两种方式解决:
方式一:在400响应中明确禁用分页
修改OpenApiResponse配置,添加pagination=False参数,告知drf-spectacular该响应不需要分页包装:
400: OpenApiResponse( response=ExceptionSerializer, pagination=False, # 新增此行,禁用分页包装 examples=[ OpenApiExample( "DATE_PARSE_ERROR", value={"api_status_code": "DATE_PARSE_ERROR", "extra": {"details": "asdf"}}, status_codes=[400], response_only=True, ) ], ),
方式二:从视图层面控制分页触发
重写视图的get_pagination_class方法,仅在响应状态为200时启用分页:
class ArchiveListView(LoginRequiredMixin, ListAPIView): model = m.Archive serializer_class = s.ArchiveListViewSerializer pagination_class = LimitOffsetPagination def get_pagination_class(self): # 仅在请求成功返回200时使用分页 if not hasattr(self, 'response') or self.response.status_code == 200: return self.pagination_class return None
第一种方式直接针对Swagger文档生成逻辑修正,操作简单;第二种方式从视图业务逻辑层面确保异常响应不会被分页处理,能同步修正文档和实际接口的响应格式。
内容的提问来源于stack exchange,提问作者jnowak
相关产品推荐
相关产品推荐

