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

Django中使用drf_yasg嵌套序列化器时出现Swagger生成错误

解决方案

核心原因

drf_yasg默认会尝试将请求序列化器解析为表单(form-data)参数,但表单格式不支持嵌套的JSON结构,因此在处理带many=True的嵌套序列化器时会抛出无法实例化的错误。

方法1:强制视图使用JSON请求格式

在视图中明确指定解析器为JSON,并通过drf_yasg的装饰器标记请求内容类型为application/json,让drf_yasg按照JSON结构生成文档:

from rest_framework.parsers import JSONParser
from drf_yasg.utils import swagger_auto_schema
from rest_framework.response import Response
from rest_framework.views import APIView

class CarCreateView(APIView):
    parser_classes = [JSONParser]  # 强制使用JSON解析器

    @swagger_auto_schema(
        request_body=CarSerializer,
        consumes=["application/json"],  # 指定请求内容类型为JSON
        responses={201: CarSerializer}
    )
    def post(self, request):
        serializer = CarSerializer(data=request.data)
        if serializer.is_valid():
            # 重写create方法处理嵌套的CarFiles保存
            serializer.save()
            return Response(serializer.data, status=201)
        return Response(serializer.errors, status=400)

同时,确保CarSerializer重写了create方法来处理嵌套数据的保存:

class CarSerializer(serializers.ModelSerializer):
    car_files = CarFilesSerializer(many=True)

    class Meta:
        model = Car
        fields = '__all__'

    def create(self, validated_data):
        # 提取嵌套的文件数据
        files_data = validated_data.pop('car_files')
        # 创建Car实例
        car = Car.objects.create(**validated_data)
        # 批量创建关联的CarFiles
        for file_data in files_data:
            CarFiles.objects.create(car=car, **file_data)
        return car

方法2:拆分输入输出序列化器

分别定义用于POST请求的输入序列化器和用于GET请求的输出序列化器,在视图中根据请求方法切换:

# 输入序列化器:处理POST请求的嵌套数据提交
class CarCreateSerializer(serializers.ModelSerializer):
    car_files = CarFilesSerializer(many=True)

    class Meta:
        model = Car
        fields = '__all__'

    def create(self, validated_data):
        files_data = validated_data.pop('car_files')
        car = Car.objects.create(**validated_data)
        for file_data in files_data:
            CarFiles.objects.create(car=car, **file_data)
        return car

# 输出序列化器:处理GET请求的嵌套数据返回
class CarSerializer(serializers.ModelSerializer):
    car_files = CarFilesSerializer(many=True, read_only=True)

    class Meta:
        model = Car
        fields = '__all__'

视图中切换序列化器:

class CarView(APIView):
    def get_serializer_class(self):
        if self.request.method == 'POST':
            return CarCreateSerializer
        return CarSerializer

    def get(self, request):
        cars = Car.objects.all()
        serializer = self.get_serializer()(cars, many=True)
        return Response(serializer.data)

    @swagger_auto_schema(
        request_body=CarCreateSerializer,
        consumes=["application/json"],
        responses={201: CarSerializer}
    )
    def post(self, request):
        serializer = self.get_serializer()(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=201)
        return Response(serializer.errors, status=400)

方法3:自定义drf_yasg字段检查器

通过自定义字段检查器,拦截drf_yasg的字段解析逻辑,让它正确识别嵌套序列化器为JSON Schema的一部分:

from drf_yasg.inspectors import FieldInspector
from drf_yasg import openapi
from rest_framework import serializers

class NestedSerializerInspector(FieldInspector):
    def field_to_swagger_object(self, field, swagger_object_type, use_references=True):
        # 处理带many=True的嵌套序列化器
        if hasattr(field, 'child') and isinstance(field.child, serializers.ModelSerializer):
            if swagger_object_type == openapi.Items:
                # 直接返回子序列化器的Schema定义
                return self.probe_field_inspectors(field.child, openapi.Schema, use_references)
        # 其他情况使用默认逻辑
        return super().field_to_swagger_object(field, swagger_object_type, use_references)

在Django配置文件中添加这个自定义检查器:

SWAGGER_SETTINGS = {
    'DEFAULT_FIELD_INSPECTORS': [
        'your_app_name.inspectors.NestedSerializerInspector',  # 替换为你的检查器路径
        'drf_yasg.inspectors.FieldInspector',
        'drf_yasg.inspectors.ReferencingSerializerInspector',
        'drf_yasg.inspectors.ChoiceFieldInspector',
        'drf_yasg.inspectors.FileFieldInspector',
        'drf_yasg.inspectors.DictFieldInspector',
        'drf_yasg.inspectors.SimpleFieldInspector',
        'drf_yasg.inspectors.StringDefaultFieldInspector',
    ],
}

内容的提问来源于stack exchange,提问作者Kaç Thon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 09:37:36