Adapts schema generation for pagination.

- add `domain` and `protocol` to `AutoSchema` init
- add `get_schema_domain` and `get_schema_protocol` to `AutoSchema`
- adapt pagination classes to accept `domain`, `protocol` and `path` for method `get_paginated_response_schema`
- adapt `test_paginated_list_response_body_generation`
  - do not use custom `Pagination` implementation, rather use `PageNumberPagination`
  - make sure new parameters `domain`, `protocol` and `path` are tested as well
This commit is contained in:
Robert Stein 2020-11-29 17:37:24 +01:00
parent 8812394ed8
commit 1c7035f721
3 changed files with 56 additions and 27 deletions

View File

@ -229,7 +229,7 @@ class PageNumberPagination(BasePagination):
('results', data)
]))
def get_paginated_response_schema(self, schema):
def get_paginated_response_schema(self, schema, url='/accounts/', domain='api.example.org', protocol='http'):
return {
'type': 'object',
'properties': {
@ -241,15 +241,15 @@ class PageNumberPagination(BasePagination):
'type': 'string',
'nullable': True,
'format': 'uri',
'example': 'http://api.example.org/accounts/?{page_query_param}=4'.format(
page_query_param=self.page_query_param)
'example': '{protocol}://{domain}{url}?{page_query_param}=4'.format(
page_query_param=self.page_query_param, protocol=protocol, domain=domain, url=url)
},
'previous': {
'type': 'string',
'nullable': True,
'format': 'uri',
'example': 'http://api.example.org/accounts/?{page_query_param}=2'.format(
page_query_param=self.page_query_param)
'example': '{protocol}://{domain}{url}?{page_query_param}=2'.format(
page_query_param=self.page_query_param, protocol=protocol, domain=domain, url=url)
},
'results': schema,
},
@ -402,7 +402,7 @@ class LimitOffsetPagination(BasePagination):
('results', data)
]))
def get_paginated_response_schema(self, schema):
def get_paginated_response_schema(self, schema, url='/accounts/', domain='api.example.org', protocol='http'):
return {
'type': 'object',
'properties': {
@ -414,15 +414,19 @@ class LimitOffsetPagination(BasePagination):
'type': 'string',
'nullable': True,
'format': 'uri',
'example': 'http://api.example.org/accounts/?{offset_param}=400&{limit_param}=100'.format(
offset_param=self.offset_query_param, limit_param=self.limit_query_param),
'example': '{protocol}://{domain}{url}?{offset_param}=400&{limit_param}=100'.format(
offset_param=self.offset_query_param, limit_param=self.limit_query_param,
protocol=protocol, domain=domain, url=url
),
},
'previous': {
'type': 'string',
'nullable': True,
'format': 'uri',
'example': 'http://api.example.org/accounts/?{offset_param}=200&{limit_param}=100'.format(
offset_param=self.offset_query_param, limit_param=self.limit_query_param),
'example': '{protocol}://{domain}{url}?{offset_param}=200&{limit_param}=100'.format(
offset_param=self.offset_query_param, limit_param=self.limit_query_param,
protocol=protocol, domain=domain, url=url
),
},
'results': schema,
},
@ -898,7 +902,7 @@ class CursorPagination(BasePagination):
('results', data)
]))
def get_paginated_response_schema(self, schema):
def get_paginated_response_schema(self, schema, url='/accounts/', domain='api.example.org', protocol='http'):
return {
'type': 'object',
'properties': {

View File

@ -118,7 +118,8 @@ class SchemaGenerator(BaseSchemaGenerator):
class AutoSchema(ViewInspector):
def __init__(self, tags=None, operation_id_base=None, component_name=None):
def __init__(self, tags=None, operation_id_base=None, component_name=None, domain='api.example.org',
protocol='http'):
"""
:param operation_id_base: user-defined name in operationId. If empty, it will be deducted from the Model/Serializer/View name.
:param component_name: user-defined component's name. If empty, it will be deducted from the Serializer's class name.
@ -128,6 +129,8 @@ class AutoSchema(ViewInspector):
self._tags = tags
self.operation_id_base = operation_id_base
self.component_name = component_name
self.domain = domain
self.protocol = protocol
super().__init__()
request_media_types = []
@ -683,7 +686,12 @@ class AutoSchema(ViewInspector):
}
paginator = self.get_paginator()
if paginator:
response_schema = paginator.get_paginated_response_schema(response_schema)
response_schema = paginator.get_paginated_response_schema(
response_schema,
url=path,
domain=self.get_schema_domain(),
protocol=self.get_schema_protocol()
)
else:
response_schema = item_schema
status_code = '201' if method == 'POST' else '200'
@ -713,6 +721,12 @@ class AutoSchema(ViewInspector):
return [path.split('/')[0].replace('_', '-')]
def get_schema_domain(self):
return self.domain
def get_schema_protocol(self):
return self.protocol
def _get_path_parameters(self, path, method):
warnings.warn(
"Method `_get_path_parameters()` has been renamed to `get_path_parameters()`. "

View File

@ -405,26 +405,22 @@ class TestOperationIntrospection(TestCase):
path = '/'
method = 'GET'
class Pagination(pagination.BasePagination):
def get_paginated_response_schema(self, schema):
return {
'type': 'object',
'item': schema,
}
class ItemSerializer(serializers.Serializer):
text = serializers.CharField()
class View(generics.GenericAPIView):
serializer_class = ItemSerializer
pagination_class = Pagination
pagination_class = pagination.PageNumberPagination
view = create_view(
View,
method,
create_request(path),
)
inspector = AutoSchema()
inspector = AutoSchema(
domain='www.django-rest-framework.org',
protocol='https'
)
inspector.view = view
responses = inspector.get_responses(path, method)
@ -435,10 +431,25 @@ class TestOperationIntrospection(TestCase):
'application/json': {
'schema': {
'type': 'object',
'item': {
'type': 'array',
'items': {
'$ref': '#/components/schemas/Item'
'properties': {
'next': {
'example': 'https://www.django-rest-framework.org/?page=4',
'format': 'uri',
'nullable': True,
'type': 'string'
},
'previous': {
'example': 'https://www.django-rest-framework.org/?page=2',
'format': 'uri',
'nullable': True,
'type': 'string'
},
'count': {'example': 123, 'type': 'integer'},
'results': {
'type': 'array',
'items': {
'$ref': '#/components/schemas/Item'
},
},
},
},
@ -583,7 +594,7 @@ class TestOperationIntrospection(TestCase):
method = 'GET'
class Pagination(pagination.BasePagination):
def get_paginated_response_schema(self, schema):
def get_paginated_response_schema(self, schema, url='/accounts/', domain='api.example.org', protocol='http'):
return {
'type': 'object',
'item': schema,