From 65a0d59c700b07adb1e492b0cd93645b671aac9a Mon Sep 17 00:00:00 2001 From: Dan Bate Date: Mon, 25 Jun 2018 16:50:45 +0100 Subject: [PATCH 1/4] added ability to add sections to custom action documentation --- rest_framework/schemas/inspectors.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/rest_framework/schemas/inspectors.py b/rest_framework/schemas/inspectors.py index 89a1fc93a5..f108e0d365 100644 --- a/rest_framework/schemas/inspectors.py +++ b/rest_framework/schemas/inspectors.py @@ -233,9 +233,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 = {'': ''} @@ -249,7 +251,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: From a138cfc6275fdbed55bcf0b44ce12ec5db6a83c4 Mon Sep 17 00:00:00 2001 From: Dan Bate Date: Tue, 26 Jun 2018 12:47:37 +0100 Subject: [PATCH 2/4] added tests to cover docs sections in custom actions --- tests/test_schemas.py | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/tests/test_schemas.py b/tests/test_schemas.py index f929fece5f..c898bdee48 100644 --- a/tests/test_schemas.py +++ b/tests/test_schemas.py @@ -104,6 +104,17 @@ 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 + if coreapi: schema_view = get_schema_view(title='Example API') @@ -150,6 +161,13 @@ def test_anonymous_request(self): action='get' ) }, + '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', @@ -245,6 +263,23 @@ def test_authenticated_request(self): action='post' ) }, + '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/{id}/', action='put', @@ -529,6 +564,13 @@ def test_schema_for_regular_views(self): action='get' ) }, + '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', From 3893d7c469ef9441a8fb4139e4575a9c3891edce Mon Sep 17 00:00:00 2001 From: Dan Bate Date: Thu, 13 Sep 2018 16:47:40 +0100 Subject: [PATCH 3/4] added method specific docs test for action mapping --- tests/test_schemas.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/test_schemas.py b/tests/test_schemas.py index cc7174cb25..ad2e34a4ba 100644 --- a/tests/test_schemas.py +++ b/tests/test_schemas.py @@ -125,6 +125,13 @@ def documented_custom_action(self, request): """ 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') @@ -296,7 +303,17 @@ def test_authenticated_request(self): 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}/', From 863f9e0fab249845fd9ab299885f670e24f60258 Mon Sep 17 00:00:00 2001 From: Dan Bate Date: Mon, 8 Oct 2018 12:57:12 +0100 Subject: [PATCH 4/4] added docs for custom action documentation --- docs/topics/documenting-your-api.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/docs/topics/documenting-your-api.md b/docs/topics/documenting-your-api.md index d57f9d6e43..574d50ad7d 100644 --- a/docs/topics/documenting-your-api.md +++ b/docs/topics/documenting-your-api.md @@ -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