Skip to content

Commit

Permalink
Merge pull request #953 from glennmatthews/u/glennmatthews-polymorphi…
Browse files Browse the repository at this point in the history
…cproxyserializer-enhancements

Add option to provide a callable for PolymorphicProxySerializer.serializers
  • Loading branch information
tfranzel committed Mar 3, 2023
2 parents e98b0c6 + 2828132 commit 4c23bde
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 2 deletions.
20 changes: 19 additions & 1 deletion drf_spectacular/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,19 @@ def create(self, request, *args, **kwargs):
*drf-spectacular* processes the serializer. In those cases you can explicitly state
the mapping with ``{'legal': LegalPersonSerializer, ...}``, but it is then your
responsibility to have a valid mapping.
It is also permissible to provide a callable with no parameters for ``serializers``,
such as a lambda that will return an appropriate list or dict when evaluated.
"""
def __init__(
self,
component_name: str,
serializers: Union[Sequence[_SerializerType], Dict[str, _SerializerType]],
serializers: Union[
Sequence[_SerializerType],
Dict[str, _SerializerType],
Callable[[], Sequence[_SerializerType]],
Callable[[], Dict[str, _SerializerType]]
],
resource_type_field_name: Optional[str],
many: Optional[bool] = None,
):
Expand All @@ -88,6 +96,16 @@ def __new__(cls, *args, **kwargs):
instance._many = many
return instance

@property
def serializers(self):
if callable(self._serializers):
self._serializers = self._serializers()
return self._serializers

@serializers.setter
def serializers(self, value):
self._serializers = value

@property
def data(self):
self._trap()
Expand Down
21 changes: 20 additions & 1 deletion tests/test_polymorphic.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,27 @@ def create(self, request, *args, **kwargs):
def partial_update(self, request, *args, **kwargs):
return Response({}) # pragma: no cover

lambda_poly_proxy = PolymorphicProxySerializer(
component_name='MetaPerson',
serializers=lambda: [LegalPersonSerializer, NaturalPersonSerializer],
resource_type_field_name='type',
)

class LambdaPersonViewSet(viewsets.GenericViewSet):
@extend_schema(request=lambda_poly_proxy, responses=lambda_poly_proxy)
def create(self, request, *args, **kwargs):
return Response({}) # pragma: no cover

@extend_schema(
request=lambda_poly_proxy,
responses=lambda_poly_proxy,
parameters=[OpenApiParameter('id', int, OpenApiParameter.PATH)],
)
def partial_update(self, request, *args, **kwargs):
return Response({}) # pragma: no cover


@pytest.mark.parametrize('viewset', [ImplicitPersonViewSet, ExplicitPersonViewSet])
@pytest.mark.parametrize('viewset', [ImplicitPersonViewSet, ExplicitPersonViewSet, LambdaPersonViewSet])
def test_polymorphic(no_warnings, viewset):
assert_schema(
generate_schema('persons', viewset),
Expand Down

0 comments on commit 4c23bde

Please sign in to comment.