Skip to content

Commit 24e13d3

Browse files
authored
Merge pull request #1304 from tfranzel/oas31_validator_fix
Oas31 validator fix
2 parents 8faf63c + 8156c0b commit 24e13d3

File tree

3 files changed

+49
-1
lines changed

3 files changed

+49
-1
lines changed

drf_spectacular/openapi.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,6 +1069,10 @@ def _map_basic_serializer(self, serializer, direction):
10691069
def _insert_field_validators(self, field, schema):
10701070
schema_type = schema.get('type')
10711071

1072+
# OAS 3.1 special case - extract the main type
1073+
if isinstance(schema_type, list):
1074+
schema_type = [t for t in schema_type if t != 'null'][0]
1075+
10721076
def update_constraint(schema, key, function, value, *, exclusive=False):
10731077
if callable(value):
10741078
value = value()

tests/test_oas31.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
from unittest import mock
22

3-
from rest_framework import serializers
3+
from rest_framework import serializers, viewsets
44
from rest_framework.views import APIView
55

66
from drf_spectacular.utils import extend_schema
77
from tests import generate_schema
8+
from tests.models import SimpleModel
89

910

1011
@mock.patch('drf_spectacular.settings.spectacular_settings.OAS_VERSION', '3.1.0')
@@ -68,3 +69,23 @@ def get(self, request):
6869
'required': ['foo'],
6970
'type': 'object'
7071
}
72+
73+
74+
@mock.patch('drf_spectacular.settings.spectacular_settings.OAS_VERSION', '3.1.0')
75+
def test_validator_addition_for_oas31(no_warnings):
76+
77+
class XSerializer(serializers.Serializer):
78+
field = serializers.CharField(allow_blank=True, allow_null=True, max_length=40, required=False)
79+
80+
class XViewset(viewsets.ModelViewSet):
81+
serializer_class = XSerializer
82+
queryset = SimpleModel.objects.none()
83+
84+
schema = generate_schema('x', XViewset)
85+
86+
assert schema['components']['schemas']['X'] == {
87+
'properties': {
88+
'field': {'maxLength': 40, 'type': ['string', 'null']}
89+
},
90+
'type': 'object'
91+
}

tests/test_regressions.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3421,3 +3421,26 @@ class XViewSet(viewsets.ReadOnlyModelViewSet):
34213421
schema = generate_schema('/x', XViewSet)
34223422
assert schema['paths']['/x/']['get']["operationId"] == 'list_x'
34233423
assert schema['paths']['/x/{id}/']['get']["operationId"] == 'retrieve_x'
3424+
3425+
3426+
class SelfReferentialSerializer(serializers.Serializer):
3427+
field_int = serializers.IntegerField()
3428+
field_self = serializers.SerializerMethodField()
3429+
3430+
def get_field_self(self) -> "SelfReferentialSerializer":
3431+
return SelfReferentialSerializer() # pragma: no cover
3432+
3433+
3434+
def test_self_referential_serializer_method_field(no_warnings):
3435+
class XViewset(viewsets.ModelViewSet):
3436+
serializer_class = SelfReferentialSerializer
3437+
queryset = SimpleModel.objects.all()
3438+
3439+
schema = generate_schema('/x', XViewset)
3440+
assert schema['components']['schemas']['SelfReferential']['properties'] == {
3441+
'field_int': {'type': 'integer'},
3442+
'field_self': {
3443+
'allOf': [{'$ref': '#/components/schemas/SelfReferential'}],
3444+
'readOnly': True
3445+
}
3446+
}

0 commit comments

Comments
 (0)