mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-07-28 00:49:49 +03:00
Always wrap response in a component schema, also paginated once, to improve processability of API code generators #7299
This commit is contained in:
parent
900773ad06
commit
558dd0e19e
|
@ -189,6 +189,8 @@ class AutoSchema(ViewInspector):
|
|||
Return components with their properties from the serializer.
|
||||
"""
|
||||
|
||||
components = {}
|
||||
|
||||
if method.lower() == 'delete':
|
||||
return {}
|
||||
|
||||
|
@ -197,10 +199,28 @@ class AutoSchema(ViewInspector):
|
|||
if not isinstance(serializer, serializers.Serializer):
|
||||
return {}
|
||||
|
||||
component_name = self.get_component_name(serializer)
|
||||
item_component_name = self.get_component_name(serializer)
|
||||
item_schema = self.map_serializer(serializer)
|
||||
components[item_component_name] = item_schema
|
||||
|
||||
content = self.map_serializer(serializer)
|
||||
return {component_name: content}
|
||||
response_component_name = self._get_response_component_name(
|
||||
self.get_operation_id(path, method)
|
||||
)
|
||||
|
||||
if is_list_view(path, method, self.view):
|
||||
response_component_schema = {
|
||||
'type': 'array',
|
||||
'items': self._get_serializer_reference(serializer),
|
||||
}
|
||||
paginator = self.get_paginator()
|
||||
if paginator:
|
||||
response_component_schema = paginator.get_paginated_response_schema(response_component_schema)
|
||||
else:
|
||||
response_component_schema = self._get_serializer_reference(serializer)
|
||||
|
||||
components[response_component_name] = response_component_schema
|
||||
|
||||
return components
|
||||
|
||||
def _to_camel_case(self, snake_str):
|
||||
components = snake_str.split('_')
|
||||
|
@ -613,9 +633,17 @@ class AutoSchema(ViewInspector):
|
|||
.format(view.__class__.__name__, method, path))
|
||||
return None
|
||||
|
||||
def _get_reference(self, serializer):
|
||||
def _get_serializer_reference(self, serializer):
|
||||
return {'$ref': '#/components/schemas/{}'.format(self.get_component_name(serializer))}
|
||||
|
||||
@staticmethod
|
||||
def _get_response_component_name(operation_id):
|
||||
operation_id = operation_id[0].upper() + operation_id[1:]
|
||||
return operation_id + 'Response'
|
||||
|
||||
def _get_response_reference(self, operation_id):
|
||||
return {'$ref': '#/components/schemas/{0}'.format(self._get_response_component_name(operation_id))}
|
||||
|
||||
def get_request_body(self, path, method):
|
||||
if method not in ('PUT', 'PATCH', 'POST'):
|
||||
return {}
|
||||
|
@ -627,7 +655,7 @@ class AutoSchema(ViewInspector):
|
|||
if not isinstance(serializer, serializers.Serializer):
|
||||
item_schema = {}
|
||||
else:
|
||||
item_schema = self._get_reference(serializer)
|
||||
item_schema = self._get_serializer_reference(serializer)
|
||||
|
||||
return {
|
||||
'content': {
|
||||
|
@ -649,20 +677,17 @@ class AutoSchema(ViewInspector):
|
|||
serializer = self.get_serializer(path, method)
|
||||
|
||||
if not isinstance(serializer, serializers.Serializer):
|
||||
item_schema = {}
|
||||
if is_list_view(path, method, self.view):
|
||||
response_schema = {
|
||||
'type': 'array',
|
||||
'items': {}
|
||||
}
|
||||
else:
|
||||
response_schema = {}
|
||||
else:
|
||||
item_schema = self._get_reference(serializer)
|
||||
|
||||
if is_list_view(path, method, self.view):
|
||||
response_schema = {
|
||||
'type': 'array',
|
||||
'items': item_schema,
|
||||
}
|
||||
paginator = self.get_paginator()
|
||||
if paginator:
|
||||
response_schema = paginator.get_paginated_response_schema(response_schema)
|
||||
else:
|
||||
response_schema = item_schema
|
||||
response_schema = self._get_response_reference(
|
||||
self.get_operation_id(path, method)
|
||||
)
|
||||
status_code = '201' if method == 'POST' else '200'
|
||||
return {
|
||||
status_code: {
|
||||
|
|
|
@ -308,7 +308,8 @@ class TestOperationIntrospection(TestCase):
|
|||
inspector.view = view
|
||||
|
||||
responses = inspector.get_responses(path, method)
|
||||
assert responses['201']['content']['application/json']['schema']['$ref'] == '#/components/schemas/Item'
|
||||
assert responses['201']['content']['application/json']['schema']['$ref'] == \
|
||||
'#/components/schemas/CreateItemResponse'
|
||||
|
||||
components = inspector.get_components(path, method)
|
||||
assert sorted(components['Item']['required']) == ['text', 'write_only']
|
||||
|
@ -338,7 +339,7 @@ class TestOperationIntrospection(TestCase):
|
|||
inspector.view = view
|
||||
|
||||
responses = inspector.get_responses(path, method)
|
||||
assert responses['201']['content']['application/json']['schema']['$ref'] == '#/components/schemas/Item'
|
||||
assert responses['201']['content']['application/json']['schema']['$ref'] == '#/components/schemas/CreateItemResponse'
|
||||
components = inspector.get_components(path, method)
|
||||
assert components['Item']
|
||||
|
||||
|
@ -375,10 +376,7 @@ class TestOperationIntrospection(TestCase):
|
|||
'content': {
|
||||
'application/json': {
|
||||
'schema': {
|
||||
'type': 'array',
|
||||
'items': {
|
||||
'$ref': '#/components/schemas/Item'
|
||||
},
|
||||
'$ref': '#/components/schemas/ListItemsResponse'
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -386,6 +384,12 @@ class TestOperationIntrospection(TestCase):
|
|||
}
|
||||
components = inspector.get_components(path, method)
|
||||
assert components == {
|
||||
'ListItemsResponse': {
|
||||
'type': 'array',
|
||||
'items': {
|
||||
'$ref': '#/components/schemas/Item',
|
||||
},
|
||||
},
|
||||
'Item': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
|
@ -431,13 +435,7 @@ class TestOperationIntrospection(TestCase):
|
|||
'content': {
|
||||
'application/json': {
|
||||
'schema': {
|
||||
'type': 'object',
|
||||
'item': {
|
||||
'type': 'array',
|
||||
'items': {
|
||||
'$ref': '#/components/schemas/Item'
|
||||
},
|
||||
},
|
||||
'$ref': '#/components/schemas/ListItemsResponse'
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -445,6 +443,15 @@ class TestOperationIntrospection(TestCase):
|
|||
}
|
||||
components = inspector.get_components(path, method)
|
||||
assert components == {
|
||||
'ListItemsResponse': {
|
||||
'type': 'object',
|
||||
'item': {
|
||||
'type': 'array',
|
||||
'items': {
|
||||
'$ref': '#/components/schemas/Item',
|
||||
},
|
||||
},
|
||||
},
|
||||
'Item': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
|
@ -601,7 +608,7 @@ class TestOperationIntrospection(TestCase):
|
|||
'content': {
|
||||
'application/json': {
|
||||
'schema': {
|
||||
'$ref': '#/components/schemas/Item'
|
||||
'$ref': '#/components/schemas/RetrieveItemResponse'
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -610,6 +617,9 @@ class TestOperationIntrospection(TestCase):
|
|||
|
||||
components = inspector.get_components(path, method)
|
||||
assert components == {
|
||||
'RetrieveItemResponse': {
|
||||
'$ref': '#/components/schemas/Item'
|
||||
},
|
||||
'Item': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
|
|
Loading…
Reference in New Issue
Block a user