diff --git a/drf_spectacular/utils.py b/drf_spectacular/utils.py index bb5361f7..a124b2fd 100644 --- a/drf_spectacular/utils.py +++ b/drf_spectacular/utils.py @@ -79,17 +79,28 @@ def __init__( ], resource_type_field_name: Optional[str], many: Optional[bool] = None, + **kwargs ): self.component_name = component_name self.serializers = serializers self.resource_type_field_name = resource_type_field_name if self._many is False: # type: ignore[attr-defined] set_override(self, 'many', False) - super().__init__() + # retain kwargs in context for potential anonymous re-init with many=True + kwargs.setdefault('context', {}).update({ + 'component_name': component_name, + 'serializers': serializers, + 'resource_type_field_name': resource_type_field_name + }) + super().__init__(**kwargs) def __new__(cls, *args, **kwargs): many = kwargs.pop('many', None) if many is True: + context = kwargs.get('context', {}) + for arg in ['component_name', 'serializers', 'resource_type_field_name']: + if arg in context: + kwargs[arg] = context.pop(arg) # re-apply retained args instance = cls.many_init(*args, **kwargs) else: instance = super().__new__(cls, *args, **kwargs) diff --git a/tests/test_polymorphic.py b/tests/test_polymorphic.py index 2f5665cf..27b2cf9d 100644 --- a/tests/test_polymorphic.py +++ b/tests/test_polymorphic.py @@ -370,3 +370,31 @@ def list(self, request, *args, **kwargs): {'type': 'array', 'items': {'$ref': '#/components/schemas/NaturalPerson'}} ] } + + +def test_polymorphic_implicit_many_through_list_method_decoration(no_warnings): + @extend_schema(responses=PolymorphicProxySerializer(**PROXY_SERIALIZER_PARAMS)) + class XViewSet(viewsets.ReadOnlyModelViewSet): + queryset = LegalPerson2.objects.none() + serializer_class = LegalPersonSerializer + + schema = generate_schema('/x', XViewSet) + + assert get_response_schema(schema['paths']['/x/']['get']) == { + 'items': {'$ref': '#/components/schemas/MetaPerson'}, 'type': 'array' + } + assert get_response_schema(schema['paths']['/x/{id}/']['get']) == { + '$ref': '#/components/schemas/MetaPerson' + } + assert schema['components']['schemas']['MetaPerson'] == { + 'discriminator': { + 'mapping': { + 'legal': '#/components/schemas/LegalPerson', + 'natural': '#/components/schemas/NaturalPerson' + }, + 'propertyName': 'type' + }, + 'oneOf': [ + {'$ref': '#/components/schemas/LegalPerson'}, {'$ref': '#/components/schemas/NaturalPerson'} + ] + }