如何用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
相关产品推荐
相关产品推荐

