Skip to content

Commit

Permalink
Merge pull request #1293 from DopustimVladimir/master
Browse files Browse the repository at this point in the history
No extra items in the oneOf list
  • Loading branch information
tfranzel authored Oct 3, 2024
2 parents 24e13d3 + 93b1ccb commit 09c5138
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 2 deletions.
7 changes: 6 additions & 1 deletion drf_spectacular/contrib/rest_polymorphic.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,13 @@ def map_serializer(self, auto_schema, direction):
f'this might lead to code generation issues.'
)

one_of_list = []
for _, ref in sub_components:
if ref not in one_of_list:
one_of_list.append(ref)

return {
'oneOf': [ref for _, ref in sub_components],
'oneOf': one_of_list,
'discriminator': {
'propertyName': serializer.resource_type_field_name,
'mapping': {resource_type: ref['$ref'] for resource_type, ref in sub_components},
Expand Down
6 changes: 5 additions & 1 deletion drf_spectacular/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,12 @@ def map_serializer(self, auto_schema, direction):
if not self._has_discriminator():
return {'oneOf': [schema for _, schema in sub_components]}
else:
one_of_list = []
for _, schema in sub_components:
if schema not in one_of_list:
one_of_list.append(schema)
return {
'oneOf': [schema for _, schema in sub_components],
'oneOf': one_of_list,
'discriminator': {
'propertyName': self.target.resource_type_field_name,
'mapping': {resource_type: schema['$ref'] for resource_type, schema in sub_components}
Expand Down
40 changes: 40 additions & 0 deletions tests/test_polymorphic.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from random import choice
from unittest import mock

import pytest
Expand Down Expand Up @@ -324,6 +325,45 @@ def view_func(request, format=None):
}


def test_polymorphic_with_default_serializer(no_warnings):
class DefaultPersonSerializer(serializers.ModelSerializer):
type = serializers.SerializerMethodField()

class Meta:
model = NaturalPerson2
fields = ('id', 'type')

def get_type(self, obj) -> str:
return choice(['basic', 'simple'])

class XViewSet(viewsets.GenericViewSet):
@extend_schema(
responses=PolymorphicProxySerializer(
component_name='MetaPerson',
serializers={
'natural': NaturalPersonSerializer,
'basic': DefaultPersonSerializer,
'simple': DefaultPersonSerializer,
},
resource_type_field_name='type',
)
)
def list(self, request, *args, **kwargs):
return Response({}) # pragma: no cover

schema = generate_schema('x', XViewSet)
components = schema['components']['schemas']
assert components['MetaPerson']['oneOf'] == [
{'$ref': '#/components/schemas/NaturalPerson'},
{'$ref': '#/components/schemas/DefaultPerson'}
]
assert components['MetaPerson']['discriminator']['mapping'] == {
'natural': '#/components/schemas/NaturalPerson',
'basic': '#/components/schemas/DefaultPerson',
'simple': '#/components/schemas/DefaultPerson'
}


def test_polymorphic_forced_many_false(no_warnings):
class XViewSet(viewsets.GenericViewSet):
@extend_schema(
Expand Down

0 comments on commit 09c5138

Please sign in to comment.