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

如何用DRF Spectacular PolymorphicProxySerializer生成OpenAPI的oneOf值?

问题

我尝试使用PolymorphicProxySerializer为一个根据下游服务状态返回不同响应的视图生成OpenAPI schema,以下是我的extend_schema_view调用代码:

device_service_get_schema = extend_schema_view(
    get=extend_schema(
        description="Get information about the status of the device driver service.",
        responses={
            200: PolymorphicProxySerializer(
                component_name="MetaDeviceService",
                serializers=[
                    inline_serializer(
                        name="DeviceServiceFailurePayload",
                        fields={
                            "timestamp": OpenApiTypes.NONE,
                            "message": OpenApiTypes.STR,
                        },
                    ),
                    inline_serializer(
                        name="DeviceServiceSuccessPayload",
                        fields={
                            "timestamp": OpenApiTypes.DATETIME,
                            "devices": OpenApiTypes.OBJECT,
                        },
                    ),
                ],
                resource_type_field_name="timestamp",
            )
        },
    )
)

运行OpenAPI生成时无错误或警告,端点定义已生成:

/api/device-service:
    get:
      operationId: device_service_retrieve
      description: Get information about the status of the device driver service.
      tags:
      - device-service
      security:
      - cookieAuth: []
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MetaDeviceService'
          description: ''

但查看生成的schema引用时,发现内联序列化器定义缺失:

MetaDeviceService:
      oneOf: []
      discriminator:
        propertyName: timestamp
        mapping: {}

注意oneOf为空,请问如何让DRF填充我定义的内联序列化器schema到oneOf中?

解决方案

问题出在OpenApiTypes.NONE的类型识别问题,以及缺少显式的判别值映射,导致DRF无法正确生成oneOf内容。按以下方式修复:

  • 替换OpenApiTypes.NONE为显式null类型
    DRF无法将OpenApiTypes.NONE解析为OpenAPI规范中的null类型,需要改成字典形式的显式定义:

    inline_serializer(
        name="DeviceServiceFailurePayload",
        fields={
            "timestamp": {"type": "null"},
            "message": OpenApiTypes.STR,
        },
    )
    
  • 添加resource_type_field_mapping显式映射
    给PolymorphicProxySerializer指定判别字段值与序列化器的对应关系,让DRF明确每个序列化器对应的判别值:

    PolymorphicProxySerializer(
        component_name="MetaDeviceService",
        serializers=[
            inline_serializer(
                name="DeviceServiceFailurePayload",
                fields={
                    "timestamp": {"type": "null"},
                    "message": OpenApiTypes.STR,
                },
            ),
            inline_serializer(
                name="DeviceServiceSuccessPayload",
                fields={
                    "timestamp": OpenApiTypes.DATETIME,
                    "devices": OpenApiTypes.OBJECT,
                },
            ),
        ],
        resource_type_field_name="timestamp",
        # 映射判别值到序列化器名称
        resource_type_field_mapping={
            None: "DeviceServiceFailurePayload",
            "string": "DeviceServiceSuccessPayload"  # DATETIME在OpenAPI中是带格式的字符串
        }
    )
    
  • 确保内联序列化器名称唯一且匹配映射
    两个内联序列化器的name必须唯一,且与resource_type_field_mapping中的值完全一致,这样DRF才能将它们注册到OpenAPI组件中并关联到oneOf数组里。

修改后重新生成schema,MetaDeviceService的oneOf会包含两个序列化器的引用,discriminator的mapping也会被正确填充。

内容的提问来源于stack exchange,提问作者Scott Wyman Neagle

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 04:15:41