Skip to content

Commit

Permalink
Merge pull request #1012 from tfranzel/poly_implicit_many
Browse files Browse the repository at this point in the history
allow implicit list expansion of PolymorphicProxySerializer #995
  • Loading branch information
tfranzel authored Jun 21, 2023
2 parents e768e5e + fbade72 commit dd645b6
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 1 deletion.
13 changes: 12 additions & 1 deletion drf_spectacular/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
28 changes: 28 additions & 0 deletions tests/test_polymorphic.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'}
]
}

0 comments on commit dd645b6

Please sign in to comment.