From 5b63919765d0da112a259da199c17c6a1f286841 Mon Sep 17 00:00:00 2001 From: Andrew Backer Date: Sun, 2 Oct 2022 23:48:26 +0100 Subject: [PATCH] Allow field extensions to return None from map_serializer_field A field can be marked as ignored when generating by using `@extended_schema_field(None)` or `OpenApiTypes.NONE`. This change extends the Extension processing so its behavior matches the decorator. --- drf_spectacular/openapi.py | 4 +++- tests/test_extensions.py | 25 +++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/drf_spectacular/openapi.py b/drf_spectacular/openapi.py index cdd8b80c..98b850b4 100644 --- a/drf_spectacular/openapi.py +++ b/drf_spectacular/openapi.py @@ -627,7 +627,9 @@ def _map_serializer_field(self, field, direction, bypass_extensions=False): serializer_field_extension = OpenApiSerializerFieldExtension.get_match(field) if serializer_field_extension and not bypass_extensions: schema = serializer_field_extension.map_serializer_field(self, direction) - if serializer_field_extension.get_name(): + if schema is None: + return None + elif serializer_field_extension.get_name(): component = ResolvedComponent( name=serializer_field_extension.get_name(), type=ResolvedComponent.SCHEMA, diff --git a/tests/test_extensions.py b/tests/test_extensions.py index 7ef2a93d..fadd463b 100644 --- a/tests/test_extensions.py +++ b/tests/test_extensions.py @@ -45,6 +45,31 @@ class XViewset(mixins.ListModelMixin, viewsets.GenericViewSet): assert schema['components']['schemas']['X']['properties']['hash']['format'] == 'byte' +def test_serializer_field_extension_can_return_none(no_warnings): + """Field extensions can return None, which should exclude them from schema""" + + class Base64FieldExtension(OpenApiSerializerFieldExtension): + target_class = 'tests.test_extensions.Base64Field' + + def map_serializer_field(self, auto_schema, direction): + return None + + # At least 1 field is required to generate schema, include 'other' + class XSerializer(serializers.Serializer): + hash = Base64Field() + other = fields.CharField() + + class XViewset(mixins.ListModelMixin, viewsets.GenericViewSet): + serializer_class = XSerializer + + schema = generate_schema('x', XViewset) + + # field 'hash' is missing from the schema output + assert schema['components']['schemas']['X'] == { + 'type': 'object', 'properties': {'other': {'type': 'string'}}, 'required': ['other'] + } + + class Base32Field(fields.Field): pass # pragma: no cover