Skip to content

Commit

Permalink
Feature/action docs sections (#6060)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
OmegaDroid authored and carltongibson committed Oct 10, 2018
1 parent 6522d4a commit 5feb835
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 3 deletions.
22 changes: 22 additions & 0 deletions docs/topics/documenting-your-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,28 @@ When using viewsets, you should use the relevant action names as delimiters.
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

Expand Down
7 changes: 4 additions & 3 deletions rest_framework/schemas/inspectors.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,9 +247,11 @@ def get_description(self, path, method):
method_docstring = getattr(view, method_name, None).__doc__
if method_docstring:
# 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()]
current_section = ''
sections = {'': ''}
Expand All @@ -263,7 +265,6 @@ def get_description(self, path, method):

# TODO: SCHEMA_COERCE_METHOD_NAMES appears here and in `SchemaGenerator.get_keys`
coerce_method_names = api_settings.SCHEMA_COERCE_METHOD_NAMES
header = getattr(view, 'action', method.lower())
if header in sections:
return sections[header].strip()
if header in coerce_method_names:
Expand Down
59 changes: 59 additions & 0 deletions tests/test_schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,24 @@ def get_serializer(self, *args, **kwargs):
assert self.action
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:
schema_view = get_schema_view(title='Example API')
Expand Down Expand Up @@ -161,6 +179,13 @@ def test_anonymous_request(self):
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(
url='/example/{id}/',
action='get',
Expand Down Expand Up @@ -263,6 +288,33 @@ def test_authenticated_request(self):
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(
url='/example/{id}/',
action='put',
Expand Down Expand Up @@ -548,6 +600,13 @@ def test_schema_for_regular_views(self):
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(
url='/example1/{id}/',
action='get',
Expand Down

0 comments on commit 5feb835

Please sign in to comment.