Skip to content

Commit 8516652

Browse files
author
Matt Daily
committed
Add ability for DRF to introspect separate request and response schemas.
This code is based off of a PR that has been merged to master in the DRF repo, but has not yet been included in a release. See encode/django-rest-framework#7424
1 parent 4f16953 commit 8516652

File tree

1 file changed

+94
-6
lines changed

1 file changed

+94
-6
lines changed

observation_portal/common/schema.py

Lines changed: 94 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
from rest_framework import serializers
12
from rest_framework.schemas.openapi import AutoSchema
3+
from rest_framework.schemas.utils import is_list_view
24

35
class ObservationPortalSchema(AutoSchema):
46
def __init__(self, tags, operation_id_base=None, component_name=None, empty_request=False, is_list_view=True):
@@ -13,11 +15,97 @@ def get_operation(self, path, method):
1315

1416
return operations
1517

18+
def get_components(self, path, method):
19+
request_serializer = self.get_request_serializer(path, method)
20+
response_serializer = self.get_response_serializer(path, method)
21+
22+
components = {}
23+
24+
if isinstance(request_serializer, serializers.Serializer):
25+
component_name = self.get_component_name(request_serializer)
26+
content = self.map_serializer(request_serializer)
27+
components.setdefault(component_name, content)
28+
29+
if isinstance(response_serializer, serializers.Serializer):
30+
component_name = self.get_component_name(response_serializer)
31+
content = self.map_serializer(response_serializer)
32+
components.setdefault(component_name, content)
33+
34+
return components
35+
36+
def get_request_serializer(self, path, method):
37+
view = self.view
38+
39+
if not hasattr(view, 'get_response_serializer'):
40+
return view.get_serializer()
41+
else:
42+
return view.get_response_serializer()
43+
44+
def get_response_serializer(self, path, method):
45+
view = self.view
46+
47+
if not hasattr(view, 'get_request_serializer'):
48+
return view.get_serializer()
49+
else:
50+
return view.get_request_serializer()
51+
52+
def get_request_body(self, path, method):
53+
if method not in ('PUT', 'PATCH', 'POST'):
54+
return {}
55+
56+
self.request_media_types = self.map_parsers(path, method)
57+
58+
serializer = self.get_response_serializer(path, method)
59+
60+
if not isinstance(serializer, serializers.Serializer):
61+
item_schema = {}
62+
else:
63+
item_schema = self._get_reference(serializer)
64+
65+
return {
66+
'content': {
67+
ct: {'schema': item_schema}
68+
for ct in self.request_media_types
69+
}
70+
}
71+
1672
def get_responses(self, path, method):
17-
responses = super().get_responses(path, method)
18-
if not self.is_list_view:
19-
list_items = responses['200']['content']['application/json']['schema'].pop('items')
20-
del responses['200']['content']['application/json']['schema']['type']
21-
responses['200']['content']['application/json']['schema'] = list_items
73+
if method == 'DELETE':
74+
return {
75+
'204': {
76+
'description': ''
77+
}
78+
}
79+
80+
self.response_media_types = self.map_renderers(path, method)
81+
82+
serializer = self.get_request_serializer(path, method)
83+
84+
if not isinstance(serializer, serializers.Serializer):
85+
item_schema = {}
86+
else:
87+
item_schema = self._get_reference(serializer)
2288

23-
return responses
89+
if is_list_view(path, method, self.view) and self.is_list_view:
90+
response_schema = {
91+
'type': 'array',
92+
'items': item_schema,
93+
}
94+
paginator = self.get_paginator()
95+
if paginator:
96+
response_schema = paginator.get_paginated_response_schema(response_schema)
97+
else:
98+
response_schema = item_schema
99+
status_code = '201' if method == 'POST' else '200'
100+
return {
101+
status_code: {
102+
'content': {
103+
ct: {'schema': response_schema}
104+
for ct in self.response_media_types
105+
},
106+
# description is a mandatory property,
107+
# https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#responseObject
108+
# TODO: put something meaningful into it
109+
'description': ""
110+
}
111+
}

0 commit comments

Comments
 (0)