From 1481111dca41875410e21545bcddab3be299bdc0 Mon Sep 17 00:00:00 2001 From: "T. Franzel" Date: Fri, 21 Jul 2023 21:14:00 +0200 Subject: [PATCH] fix django-polymorphic empty serializer case #1029 #542 --- drf_spectacular/contrib/rest_polymorphic.py | 29 ++++++++++++--------- tests/contrib/test_rest_polymorphic.py | 7 +++++ 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/drf_spectacular/contrib/rest_polymorphic.py b/drf_spectacular/contrib/rest_polymorphic.py index 3505ffc3..431fb974 100644 --- a/drf_spectacular/contrib/rest_polymorphic.py +++ b/drf_spectacular/contrib/rest_polymorphic.py @@ -20,7 +20,12 @@ def map_serializer(self, auto_schema, direction): resource_type = serializer.to_resource_type(sub_model) component = auto_schema.resolve_serializer(sub_serializer, direction) if not component: - continue + # rebuild a virtual schema-less component to model empty serializers + component = ResolvedComponent( + name=auto_schema._get_serializer_name(sub_serializer, direction), + type=ResolvedComponent.SCHEMA, + object='virtual' + ) typed_component = self.build_typed_component( auto_schema=auto_schema, component=component, @@ -49,21 +54,21 @@ def build_typed_component(self, auto_schema, component, resource_type_field_name else: typed_component_name = f'{component.name}Typed' + resource_type_schema = build_object_type( + properties={resource_type_field_name: build_basic_type(OpenApiTypes.STR)}, + required=None if patched else [resource_type_field_name] + ) + # if sub-serializer has an empty schema, only expose the resource_type field part + if component.schema: + schema = {'allOf': [resource_type_schema, component.ref]} + else: + schema = resource_type_schema + component_typed = ResolvedComponent( name=typed_component_name, type=ResolvedComponent.SCHEMA, object=component.object, - schema={ - 'allOf': [ - build_object_type( - properties={ - resource_type_field_name: build_basic_type(OpenApiTypes.STR) - }, - required=None if patched else [resource_type_field_name] - ), - component.ref, - ] - } + schema=schema, ) auto_schema.registry.register_on_missing(component_typed) return component_typed diff --git a/tests/contrib/test_rest_polymorphic.py b/tests/contrib/test_rest_polymorphic.py index 0d35433f..4c5221a6 100644 --- a/tests/contrib/test_rest_polymorphic.py +++ b/tests/contrib/test_rest_polymorphic.py @@ -113,10 +113,17 @@ def test_rest_polymorphic_split_request_with_ro_serializer(no_warnings): assert components['PersonRequest']['oneOf'] == [ {'$ref': '#/components/schemas/LegalPersonTypedRequest'}, {'$ref': '#/components/schemas/NaturalPersonTypedRequest'}, + {'$ref': '#/components/schemas/NomadicPersonTypedRequest'}, ] assert components['PersonRequest']['discriminator']['mapping'] == { 'legal': '#/components/schemas/LegalPersonTypedRequest', 'natural': '#/components/schemas/NaturalPersonTypedRequest', + 'nomadic': '#/components/schemas/NomadicPersonTypedRequest', + } + assert components['NomadicPersonTypedRequest'] == { + 'properties': {'resourcetype': {'type': 'string'}}, + 'required': ['resourcetype'], + 'type': 'object', }