mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-08-04 20:40:14 +03:00
Allow @detail_route and @list_route methods to have docstring sections.
If a method decorated as a @detail_route or @list_route has a docstring that includes sections named after the action for the http methods that are supported for that route, then they will be used for the description in the schema associated with that http method for the view.
This commit is contained in:
parent
aa10958627
commit
f772d72093
|
@ -69,6 +69,20 @@ When using viewsets, you should use the relevant action names as delimiters.
|
|||
Create a new user instance.
|
||||
"""
|
||||
|
||||
When using the `@detail_route` or `@list_route` decorators, the docstring for
|
||||
the decorated method may use the `action:` style delimiters.
|
||||
|
||||
class UserViewSet(viewsets.ModelViewSet):
|
||||
@detail_route(methods=('get', 'post'))
|
||||
def groups(self, request, pk=None):
|
||||
"""
|
||||
retrieve:
|
||||
Return the groups for the given user.
|
||||
|
||||
create:
|
||||
Add the user to a new group.
|
||||
"""
|
||||
|
||||
---
|
||||
|
||||
## Third party packages
|
||||
|
|
|
@ -8,7 +8,7 @@ from django.core.exceptions import PermissionDenied
|
|||
from django.db import models
|
||||
from django.http import Http404
|
||||
from django.utils import six
|
||||
from django.utils.encoding import force_text, smart_text
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from rest_framework import exceptions, renderers, serializers
|
||||
|
@ -19,7 +19,6 @@ from rest_framework.compat import (
|
|||
from rest_framework.request import clone_request
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.settings import api_settings
|
||||
from rest_framework.utils import formatting
|
||||
from rest_framework.utils.model_meta import _get_pk
|
||||
from rest_framework.views import APIView
|
||||
|
||||
|
@ -467,31 +466,36 @@ class SchemaGenerator(object):
|
|||
This will be based on the method docstring if one exists,
|
||||
or else the class docstring.
|
||||
"""
|
||||
method_name = getattr(view, 'action', method.lower())
|
||||
method_docstring = getattr(view, method_name, None).__doc__
|
||||
if method_docstring:
|
||||
method = method.lower()
|
||||
method_name = getattr(view, 'action', method)
|
||||
view_method = getattr(view, method_name, None)
|
||||
description = None
|
||||
if view_method:
|
||||
# An explicit docstring on the method or action.
|
||||
return formatting.dedent(smart_text(method_docstring))
|
||||
|
||||
description = view.get_view_description()
|
||||
description = api_settings.VIEW_DESCRIPTION_FUNCTION(view_method)
|
||||
if not description:
|
||||
description = view.get_view_description()
|
||||
lines = [line.strip() for line in description.splitlines()]
|
||||
current_section = ''
|
||||
sections = {'': ''}
|
||||
|
||||
for line in lines:
|
||||
if header_regex.match(line):
|
||||
current_section, seperator, lead = line.partition(':')
|
||||
current_section, separator, lead = line.partition(':')
|
||||
sections[current_section] = lead.strip()
|
||||
else:
|
||||
sections[current_section] += '\n' + line
|
||||
|
||||
header = getattr(view, 'action', method.lower())
|
||||
if header in sections:
|
||||
return sections[header].strip()
|
||||
if header in self.coerce_method_names:
|
||||
if self.coerce_method_names[header] in sections:
|
||||
return sections[self.coerce_method_names[header]].strip()
|
||||
return sections[''].strip()
|
||||
section_name = ''
|
||||
for attempt in (method_name, self.default_mapping.get(method, method)):
|
||||
if attempt in sections:
|
||||
section_name = attempt
|
||||
break
|
||||
if self.coerce_method_names.get(attempt) in sections:
|
||||
section_name = self.coerce_method_names[attempt]
|
||||
break
|
||||
|
||||
return sections[section_name].strip()
|
||||
|
||||
def get_encoding(self, path, method, view):
|
||||
"""
|
||||
|
|
|
@ -55,7 +55,19 @@ class ExampleViewSet(ModelViewSet):
|
|||
"""
|
||||
A description of custom action.
|
||||
"""
|
||||
return super(ExampleSerializer, self).retrieve(self, request)
|
||||
return super(ExampleViewSet, self).retrieve(self, request)
|
||||
|
||||
@detail_route(methods=['get', 'post'], serializer_class=EmptySerializer)
|
||||
def custom_action2(self, request, pk):
|
||||
"""
|
||||
read: A description for getting items.
|
||||
|
||||
create: A description for creating items.
|
||||
"""
|
||||
if request.method == 'GET':
|
||||
return super(ExampleViewSet, self).retrieve(self, request)
|
||||
else:
|
||||
return super(ExampleViewSet, self).create(self, request)
|
||||
|
||||
@list_route()
|
||||
def custom_list_action(self, request):
|
||||
|
@ -105,6 +117,16 @@ class TestRouterGeneratedSchema(TestCase):
|
|||
coreapi.Field('ordering', required=False, location='query', schema=coreschema.String(title='Ordering', description='Which field to use when ordering the results.'))
|
||||
]
|
||||
),
|
||||
'custom_action2': {
|
||||
'read': coreapi.Link(
|
||||
url='/example/{id}/custom_action2/',
|
||||
action='get',
|
||||
description='A description for getting items.',
|
||||
fields=[
|
||||
coreapi.Field('id', required=True, location='path', schema=coreschema.String()),
|
||||
],
|
||||
),
|
||||
},
|
||||
'custom_list_action': coreapi.Link(
|
||||
url='/example/custom_list_action/',
|
||||
action='get'
|
||||
|
@ -173,6 +195,24 @@ class TestRouterGeneratedSchema(TestCase):
|
|||
coreapi.Field('d', required=False, location='form', schema=coreschema.String(title='D')),
|
||||
]
|
||||
),
|
||||
'custom_action2': {
|
||||
'read': coreapi.Link(
|
||||
url='/example/{id}/custom_action2/',
|
||||
action='get',
|
||||
description='A description for getting items.',
|
||||
fields=[
|
||||
coreapi.Field('id', required=True, location='path', schema=coreschema.String()),
|
||||
],
|
||||
),
|
||||
'create': coreapi.Link(
|
||||
url='/example/{id}/custom_action2/',
|
||||
action='post',
|
||||
description='A description for creating items.',
|
||||
fields=[
|
||||
coreapi.Field('id', required=True, location='path', schema=coreschema.String()),
|
||||
],
|
||||
),
|
||||
},
|
||||
'custom_list_action': coreapi.Link(
|
||||
url='/example/custom_list_action/',
|
||||
action='get'
|
||||
|
|
Loading…
Reference in New Issue
Block a user