Feature/action docs sections (#6060)

* added ability to add sections to custom action documentation

* added tests to cover docs sections in custom actions

* added method specific docs test for action mapping

* added docs for custom action documentation
This commit is contained in:
Daniel Bate 2018-10-10 09:29:29 +01:00 committed by Carlton Gibson
parent 6522d4ae20
commit 5feb835929
3 changed files with 85 additions and 3 deletions

View File

@ -90,6 +90,28 @@ When using viewsets, you should use the relevant action names as delimiters.
Create a new user instance. Create a new user instance.
""" """
Custom actions on viewsets can also be documented in a similar way using the method names
as delimiters or by attaching the documentation to action mapping methods.
class UserViewSet(viewsets.ModelViewset):
...
@action(detail=False, methods=['get', 'post'])
def some_action(self, request, *args, **kwargs):
"""
get:
A description of the get method on the custom action.
post:
A description of the post method on the custom action.
"""
@some_action.mapping.put
def put_some_action():
"""
A description of the put method on the custom action.
"""
### `documentation` API Reference ### `documentation` API Reference

View File

@ -247,9 +247,11 @@ class AutoSchema(ViewInspector):
method_docstring = getattr(view, method_name, None).__doc__ method_docstring = getattr(view, method_name, None).__doc__
if method_docstring: if method_docstring:
# An explicit docstring on the method or action. # An explicit docstring on the method or action.
return formatting.dedent(smart_text(method_docstring)) return self._get_description_section(view, method.lower(), formatting.dedent(smart_text(method_docstring)))
else:
return self._get_description_section(view, getattr(view, 'action', method.lower()), view.get_view_description())
description = view.get_view_description() def _get_description_section(self, view, header, description):
lines = [line for line in description.splitlines()] lines = [line for line in description.splitlines()]
current_section = '' current_section = ''
sections = {'': ''} sections = {'': ''}
@ -263,7 +265,6 @@ class AutoSchema(ViewInspector):
# TODO: SCHEMA_COERCE_METHOD_NAMES appears here and in `SchemaGenerator.get_keys` # TODO: SCHEMA_COERCE_METHOD_NAMES appears here and in `SchemaGenerator.get_keys`
coerce_method_names = api_settings.SCHEMA_COERCE_METHOD_NAMES coerce_method_names = api_settings.SCHEMA_COERCE_METHOD_NAMES
header = getattr(view, 'action', method.lower())
if header in sections: if header in sections:
return sections[header].strip() return sections[header].strip()
if header in coerce_method_names: if header in coerce_method_names:

View File

@ -114,6 +114,24 @@ class ExampleViewSet(ModelViewSet):
assert self.action assert self.action
return super(ExampleViewSet, self).get_serializer(*args, **kwargs) return super(ExampleViewSet, self).get_serializer(*args, **kwargs)
@action(methods=['get', 'post'], detail=False)
def documented_custom_action(self, request):
"""
get:
A description of the get method on the custom action.
post:
A description of the post method on the custom action.
"""
pass
@documented_custom_action.mapping.put
def put_documented_custom_action(self, request, *args, **kwargs):
"""
A description of the put method on the custom action from mapping.
"""
pass
if coreapi: if coreapi:
schema_view = get_schema_view(title='Example API') schema_view = get_schema_view(title='Example API')
@ -161,6 +179,13 @@ class TestRouterGeneratedSchema(TestCase):
description='Custom description.', description='Custom description.',
) )
}, },
'documented_custom_action': {
'read': coreapi.Link(
url='/example/documented_custom_action/',
action='get',
description='A description of the get method on the custom action.',
)
},
'read': coreapi.Link( 'read': coreapi.Link(
url='/example/{id}/', url='/example/{id}/',
action='get', action='get',
@ -263,6 +288,33 @@ class TestRouterGeneratedSchema(TestCase):
description='Deletion description.', description='Deletion description.',
), ),
}, },
'documented_custom_action': {
'read': coreapi.Link(
url='/example/documented_custom_action/',
action='get',
description='A description of the get method on the custom action.',
),
'create': coreapi.Link(
url='/example/documented_custom_action/',
action='post',
description='A description of the post method on the custom action.',
encoding='application/json',
fields=[
coreapi.Field('a', required=True, location='form', schema=coreschema.String(title='A', description='A field description')),
coreapi.Field('b', required=False, location='form', schema=coreschema.String(title='B'))
]
),
'update': coreapi.Link(
url='/example/documented_custom_action/',
action='put',
description='A description of the put method on the custom action from mapping.',
encoding='application/json',
fields=[
coreapi.Field('a', required=True, location='form', schema=coreschema.String(title='A', description='A field description')),
coreapi.Field('b', required=False, location='form', schema=coreschema.String(title='B'))
]
),
},
'update': coreapi.Link( 'update': coreapi.Link(
url='/example/{id}/', url='/example/{id}/',
action='put', action='put',
@ -548,6 +600,13 @@ class TestSchemaGeneratorWithMethodLimitedViewSets(TestCase):
description='Custom description.', description='Custom description.',
) )
}, },
'documented_custom_action': {
'read': coreapi.Link(
url='/example1/documented_custom_action/',
action='get',
description='A description of the get method on the custom action.',
),
},
'read': coreapi.Link( 'read': coreapi.Link(
url='/example1/{id}/', url='/example1/{id}/',
action='get', action='get',