如何让drf_spectacular识别自定义MultipartJsonParser生成正确Schema
解决drf_spectacular适配自定义MultipartJsonParser的Schema问题
场景说明
我在POST端点使用自定义MultipartJsonParser,同时支持文件上传和嵌套对象,Parser代码如下:
class MultipartJsonParser(parsers.MultiPartParser): def parse(self, stream, media_type=None, parser_context=None): result = super().parse(stream, media_type=media_type, parser_context=parser_context) return parsers.DataAndFiles(json.loads(result.data["data"]), result.files)
请求以multipart/form-data格式提交,仅包含一个data键,值为序列化器对应的JSON字符串,示例:
data: "{\"about\": {\"name\": \"a\"}}"
序列化器定义:
class AboutSerializer(serializers.Serializer): name = serializers.CharField() class FooSerializer(serializers.Serializer): about = AboutSerializer() # 更多字段
当前drf_spectacular生成的Schema错误显示需要about字段,实际应显示仅含data字段(值为FooSerializer的JSON编码版本),以下是两种解决办法:
方案一:用@extend_schema手动指定请求体
适合单个视图快速调整,步骤如下:
- 定义外层序列化器,包裹
data字段:
from rest_framework import serializers class MultipartDataSerializer(serializers.Serializer): data = serializers.JSONField(schema=FooSerializer()) # 若需支持文件上传,添加FileField # file = serializers.FileField(required=False)
- 在视图的POST方法上添加装饰器,指定自定义请求体:
from drf_spectacular.utils import extend_schema from rest_framework.views import APIView from rest_framework import status, Response class FooView(APIView): parser_classes = [MultipartJsonParser] @extend_schema(request=MultipartDataSerializer) def post(self, request): serializer = FooSerializer(data=request.data) if serializer.is_valid(): # 业务逻辑处理 return Response(serializer.data) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
方案二:自定义Parser扩展实现全局生效
如果多个视图使用该Parser,可通过自定义扩展让drf_spectacular全局识别:
- 编写Parser扩展类:
from drf_spectacular.extensions import OpenApiParserExtension from drf_spectacular.plumbing import build_basic_type from drf_spectacular.types import OpenApiTypes class MultipartJsonParserExtension(OpenApiParserExtension): # 替换为你的MultipartJsonParser的完整路径 target_class = 'your_app.parsers.MultipartJsonParser' priority = 1 def get_media_type(self): return 'multipart/form-data' def get_request_schema(self, serializer): # 构建原序列化器的Schema结构 inner_schema = build_basic_type(OpenApiTypes.OBJECT, schema=serializer) return { 'type': 'object', 'properties': { 'data': { 'type': 'string', 'format': 'json', 'description': '请求数据的JSON编码字符串', 'example': '{"about": {"name": "a"}}', 'schema': inner_schema } # 支持文件上传时添加以下配置 # 'file': {'type': 'string', 'format': 'binary'} }, 'required': ['data'] }
- 在项目settings.py中注册该扩展:
DRF_SPECTACULAR_SETTINGS = { 'EXTENSIONS': [ 'your_app.extensions.MultipartJsonParserExtension', ], }
注意事项
- 若涉及文件上传,需在Schema中同步添加对应的文件字段配置,与Parser处理逻辑保持一致
- 方案一灵活度高,适合局部调整;方案二适合全局统一适配
- 配置完成后,重新生成Schema即可看到正确的请求体结构
内容的提问来源于stack exchange,提问作者Luciano
相关产品推荐
相关产品推荐

