Skip to content

Commit 7dd969d

Browse files
author
Ryan P Kilby
committed
Add 'name' and 'description' attributes to APIView
Views may now provide their `name` and `description` attributes directly, instead of relying on view introspection to derive them. These attributes may also be provided with the view's initkwargs. The `@action` decorator now provides the `name` and `description` to the view's initkwargs. By default, these values are derived from the method name and its docstring. The `name` may be overridden by providing it as an argument to the decorator. The `get_view_name` and `get_view_description` hooks now provide the view instance to the handler, instead of the view class.
1 parent ee521ea commit 7dd969d

File tree

2 files changed

+27
-7
lines changed

2 files changed

+27
-7
lines changed

rest_framework/decorators.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import types
1212
import warnings
1313

14+
from django.forms.utils import pretty_name
1415
from django.utils import six
1516

1617
from rest_framework.views import APIView
@@ -130,7 +131,7 @@ def decorator(func):
130131
return decorator
131132

132133

133-
def action(methods=None, detail=None, url_path=None, url_name=None, **kwargs):
134+
def action(methods=None, detail=None, name=None, url_path=None, url_name=None, **kwargs):
134135
"""
135136
Mark a ViewSet method as a routable action.
136137
@@ -147,9 +148,14 @@ def action(methods=None, detail=None, url_path=None, url_name=None, **kwargs):
147148
def decorator(func):
148149
func.bind_to_methods = methods
149150
func.detail = detail
151+
func.name = name if name else pretty_name(func.__name__)
150152
func.url_path = url_path if url_path else func.__name__
151153
func.url_name = url_name if url_name else func.__name__.replace('_', '-')
152154
func.kwargs = kwargs
155+
func.kwargs.update({
156+
'name': func.name,
157+
'description': func.__doc__ or None
158+
})
153159
return func
154160
return decorator
155161

rest_framework/views.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,31 +21,41 @@
2121
from rest_framework.utils import formatting
2222

2323

24-
def get_view_name(view_cls, suffix=None):
24+
def get_view_name(view):
2525
"""
2626
Given a view class, return a textual name to represent the view.
2727
This name is used in the browsable API, and in OPTIONS responses.
2828
2929
This function is the default for the `VIEW_NAME_FUNCTION` setting.
3030
"""
31-
name = view_cls.__name__
31+
if view.name is not None:
32+
return view.name
33+
34+
name = view.__class__.__name__
3235
name = formatting.remove_trailing_string(name, 'View')
3336
name = formatting.remove_trailing_string(name, 'ViewSet')
3437
name = formatting.camelcase_to_spaces(name)
38+
39+
# Suffix may be set by some Views, such as a ViewSet.
40+
suffix = getattr(view, 'suffix', None)
3541
if suffix:
3642
name += ' ' + suffix
3743

3844
return name
3945

4046

41-
def get_view_description(view_cls, html=False):
47+
def get_view_description(view, html=False):
4248
"""
4349
Given a view class, return a textual description to represent the view.
4450
This name is used in the browsable API, and in OPTIONS responses.
4551
4652
This function is the default for the `VIEW_DESCRIPTION_FUNCTION` setting.
4753
"""
48-
description = view_cls.__doc__ or ''
54+
if view.description is not None:
55+
description = view.description
56+
else:
57+
description = view.__class__.__doc__ or ''
58+
4959
description = formatting.dedent(smart_text(description))
5060
if html:
5161
return formatting.markup_description(description)
@@ -93,6 +103,10 @@ def exception_handler(exc, context):
93103

94104
class APIView(View):
95105

106+
# Allow the view name and description to be set by the initkwargs.
107+
name = None
108+
description = None
109+
96110
# The following policies may be set at either globally, or per-view.
97111
renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
98112
parser_classes = api_settings.DEFAULT_PARSER_CLASSES
@@ -224,15 +238,15 @@ def get_view_name(self):
224238
browsable API.
225239
"""
226240
func = self.settings.VIEW_NAME_FUNCTION
227-
return func(self.__class__, getattr(self, 'suffix', None))
241+
return func(self)
228242

229243
def get_view_description(self, html=False):
230244
"""
231245
Return some descriptive text for the view, as used in OPTIONS responses
232246
and in the browsable API.
233247
"""
234248
func = self.settings.VIEW_DESCRIPTION_FUNCTION
235-
return func(self.__class__, html)
249+
return func(self, html)
236250

237251
# API policy instantiation methods
238252

0 commit comments

Comments
 (0)