Skip to content

Commit 09c5138

Browse files
authored
Merge pull request #1293 from DopustimVladimir/master
No extra items in the oneOf list
2 parents 24e13d3 + 93b1ccb commit 09c5138

File tree

3 files changed

+51
-2
lines changed

3 files changed

+51
-2
lines changed

drf_spectacular/contrib/rest_polymorphic.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,13 @@ def map_serializer(self, auto_schema, direction):
4242
f'this might lead to code generation issues.'
4343
)
4444

45+
one_of_list = []
46+
for _, ref in sub_components:
47+
if ref not in one_of_list:
48+
one_of_list.append(ref)
49+
4550
return {
46-
'oneOf': [ref for _, ref in sub_components],
51+
'oneOf': one_of_list,
4752
'discriminator': {
4853
'propertyName': serializer.resource_type_field_name,
4954
'mapping': {resource_type: ref['$ref'] for resource_type, ref in sub_components},

drf_spectacular/serializers.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,12 @@ def map_serializer(self, auto_schema, direction):
2020
if not self._has_discriminator():
2121
return {'oneOf': [schema for _, schema in sub_components]}
2222
else:
23+
one_of_list = []
24+
for _, schema in sub_components:
25+
if schema not in one_of_list:
26+
one_of_list.append(schema)
2327
return {
24-
'oneOf': [schema for _, schema in sub_components],
28+
'oneOf': one_of_list,
2529
'discriminator': {
2630
'propertyName': self.target.resource_type_field_name,
2731
'mapping': {resource_type: schema['$ref'] for resource_type, schema in sub_components}

tests/test_polymorphic.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from random import choice
12
from unittest import mock
23

34
import pytest
@@ -324,6 +325,45 @@ def view_func(request, format=None):
324325
}
325326

326327

328+
def test_polymorphic_with_default_serializer(no_warnings):
329+
class DefaultPersonSerializer(serializers.ModelSerializer):
330+
type = serializers.SerializerMethodField()
331+
332+
class Meta:
333+
model = NaturalPerson2
334+
fields = ('id', 'type')
335+
336+
def get_type(self, obj) -> str:
337+
return choice(['basic', 'simple'])
338+
339+
class XViewSet(viewsets.GenericViewSet):
340+
@extend_schema(
341+
responses=PolymorphicProxySerializer(
342+
component_name='MetaPerson',
343+
serializers={
344+
'natural': NaturalPersonSerializer,
345+
'basic': DefaultPersonSerializer,
346+
'simple': DefaultPersonSerializer,
347+
},
348+
resource_type_field_name='type',
349+
)
350+
)
351+
def list(self, request, *args, **kwargs):
352+
return Response({}) # pragma: no cover
353+
354+
schema = generate_schema('x', XViewSet)
355+
components = schema['components']['schemas']
356+
assert components['MetaPerson']['oneOf'] == [
357+
{'$ref': '#/components/schemas/NaturalPerson'},
358+
{'$ref': '#/components/schemas/DefaultPerson'}
359+
]
360+
assert components['MetaPerson']['discriminator']['mapping'] == {
361+
'natural': '#/components/schemas/NaturalPerson',
362+
'basic': '#/components/schemas/DefaultPerson',
363+
'simple': '#/components/schemas/DefaultPerson'
364+
}
365+
366+
327367
def test_polymorphic_forced_many_false(no_warnings):
328368
class XViewSet(viewsets.GenericViewSet):
329369
@extend_schema(

0 commit comments

Comments
 (0)