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

如何让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手动指定请求体

适合单个视图快速调整,步骤如下:

  1. 定义外层序列化器,包裹data字段:
from rest_framework import serializers

class MultipartDataSerializer(serializers.Serializer):
    data = serializers.JSONField(schema=FooSerializer())
    # 若需支持文件上传,添加FileField
    # file = serializers.FileField(required=False)
  1. 在视图的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全局识别:

  1. 编写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']
        }
  1. 在项目settings.py中注册该扩展:
DRF_SPECTACULAR_SETTINGS = {
    'EXTENSIONS': [
        'your_app.extensions.MultipartJsonParserExtension',
    ],
}

注意事项

  • 若涉及文件上传,需在Schema中同步添加对应的文件字段配置,与Parser处理逻辑保持一致
  • 方案一灵活度高,适合局部调整;方案二适合全局统一适配
  • 配置完成后,重新生成Schema即可看到正确的请求体结构

内容的提问来源于stack exchange,提问作者Luciano

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 22:13:17