Skip to content

Commit 9c97946

Browse files
Make api_view respect standard wrapper assignments (#8291)
1 parent d0bb4d8 commit 9c97946

File tree

2 files changed

+14
-16
lines changed

2 files changed

+14
-16
lines changed

rest_framework/decorators.py

+4-16
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
methods on viewsets that should be included by routers.
88
"""
99
import types
10+
from functools import update_wrapper
1011

1112
from django.forms.utils import pretty_name
1213

@@ -22,18 +23,8 @@ def api_view(http_method_names=None):
2223

2324
def decorator(func):
2425

25-
WrappedAPIView = type(
26-
'WrappedAPIView',
27-
(APIView,),
28-
{'__doc__': func.__doc__}
29-
)
30-
31-
# Note, the above allows us to set the docstring.
32-
# It is the equivalent of:
33-
#
34-
# class WrappedAPIView(APIView):
35-
# pass
36-
# WrappedAPIView.__doc__ = func.doc <--- Not possible to do this
26+
class WrappedAPIView(APIView):
27+
pass
3728

3829
# api_view applied without (method_names)
3930
assert not(isinstance(http_method_names, types.FunctionType)), \
@@ -52,9 +43,6 @@ def handler(self, *args, **kwargs):
5243
for method in http_method_names:
5344
setattr(WrappedAPIView, method.lower(), handler)
5445

55-
WrappedAPIView.__name__ = func.__name__
56-
WrappedAPIView.__module__ = func.__module__
57-
5846
WrappedAPIView.renderer_classes = getattr(func, 'renderer_classes',
5947
APIView.renderer_classes)
6048

@@ -73,7 +61,7 @@ def handler(self, *args, **kwargs):
7361
WrappedAPIView.schema = getattr(func, 'schema',
7462
APIView.schema)
7563

76-
return WrappedAPIView.as_view()
64+
return update_wrapper(WrappedAPIView.as_view(), func)
7765

7866
return decorator
7967

tests/test_decorators.py

+10
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,16 @@ def view(request):
162162

163163
assert isinstance(view.cls.schema, CustomSchema)
164164

165+
def test_wrapper_assignments(self):
166+
@api_view(["GET"])
167+
def test_view(request):
168+
"""example docstring"""
169+
pass
170+
171+
assert test_view.__name__ == "test_view"
172+
assert test_view.__doc__ == "example docstring"
173+
assert test_view.__qualname__ == "DecoratorTestCase.test_wrapper_assignments.<locals>.test_view"
174+
165175

166176
class ActionDecoratorTestCase(TestCase):
167177

0 commit comments

Comments
 (0)