mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-07-28 17:09:59 +03:00
Add extra_attrs decorator for function-based view.
In this way, function-based view will have same behavior with class view.
This commit is contained in:
parent
a73d3c309f
commit
f2c8773e05
|
@ -217,6 +217,21 @@ You may pass `None` in order to exclude the view from schema generation.
|
||||||
return Response({"message": "Will not appear in schema!"})
|
return Response({"message": "Will not appear in schema!"})
|
||||||
|
|
||||||
|
|
||||||
|
## View extra attrs decorator
|
||||||
|
|
||||||
|
To set custom extra attribute on function-based view, you may use the `@extra_attrs` decorator.
|
||||||
|
This must come *after* (below) the `@api_view` decorator. For example:
|
||||||
|
|
||||||
|
from rest_framework.decorators import api_view, extra_attrs
|
||||||
|
|
||||||
|
class ExtraClass:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@api_view(['GET'])
|
||||||
|
@extra_attrs(extra_class=ExtraClass)
|
||||||
|
def view(request):
|
||||||
|
return Response({"message": "Hello for today! See you tomorrow!"})
|
||||||
|
|
||||||
[cite]: https://reinout.vanrees.org/weblog/2011/08/24/class-based-views-usage.html
|
[cite]: https://reinout.vanrees.org/weblog/2011/08/24/class-based-views-usage.html
|
||||||
[cite2]: http://www.boredomandlaziness.org/2012/05/djangos-cbvs-are-not-mistake-but.html
|
[cite2]: http://www.boredomandlaziness.org/2012/05/djangos-cbvs-are-not-mistake-but.html
|
||||||
[settings]: settings.md
|
[settings]: settings.md
|
||||||
|
|
|
@ -72,6 +72,11 @@ def api_view(http_method_names=None):
|
||||||
|
|
||||||
WrappedAPIView.schema = getattr(func, 'schema',
|
WrappedAPIView.schema = getattr(func, 'schema',
|
||||||
APIView.schema)
|
APIView.schema)
|
||||||
|
for extra_attr in getattr(func, 'extra_attrs', []):
|
||||||
|
assert not (hasattr(WrappedAPIView, extra_attr)), \
|
||||||
|
'{} already has attribute {}'.format(func.__name__, extra_attr)
|
||||||
|
setattr(WrappedAPIView, extra_attr,
|
||||||
|
getattr(func, extra_attr, None))
|
||||||
|
|
||||||
return WrappedAPIView.as_view()
|
return WrappedAPIView.as_view()
|
||||||
|
|
||||||
|
@ -120,6 +125,15 @@ def schema(view_inspector):
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
|
def extra_attrs(**kwargs):
|
||||||
|
def decorator(func):
|
||||||
|
func.extra_attrs = list(kwargs.keys())
|
||||||
|
for extra_attr, val in kwargs.items():
|
||||||
|
setattr(func, extra_attr, val)
|
||||||
|
return func
|
||||||
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
def action(methods=None, detail=None, url_path=None, url_name=None, **kwargs):
|
def action(methods=None, detail=None, url_path=None, url_name=None, **kwargs):
|
||||||
"""
|
"""
|
||||||
Mark a ViewSet method as a routable action.
|
Mark a ViewSet method as a routable action.
|
||||||
|
|
|
@ -4,7 +4,7 @@ from django.test import TestCase
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework.authentication import BasicAuthentication
|
from rest_framework.authentication import BasicAuthentication
|
||||||
from rest_framework.decorators import (
|
from rest_framework.decorators import (
|
||||||
action, api_view, authentication_classes, parser_classes,
|
action, api_view, authentication_classes, extra_attrs, parser_classes,
|
||||||
permission_classes, renderer_classes, schema, throttle_classes
|
permission_classes, renderer_classes, schema, throttle_classes
|
||||||
)
|
)
|
||||||
from rest_framework.parsers import JSONParser
|
from rest_framework.parsers import JSONParser
|
||||||
|
@ -166,6 +166,25 @@ class DecoratorTestCase(TestCase):
|
||||||
|
|
||||||
assert isinstance(view.cls.schema, CustomSchema)
|
assert isinstance(view.cls.schema, CustomSchema)
|
||||||
|
|
||||||
|
def test_extra_attrs(self):
|
||||||
|
"""
|
||||||
|
Checks Custom extra attrs is set on view
|
||||||
|
"""
|
||||||
|
|
||||||
|
def extra_func():
|
||||||
|
pass
|
||||||
|
|
||||||
|
class ExtraClass:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@api_view(['get'])
|
||||||
|
@extra_attrs(extra_func=extra_func, extra_class=ExtraClass)
|
||||||
|
def view(request):
|
||||||
|
return Response({})
|
||||||
|
|
||||||
|
assert view.cls.extra_func is extra_func
|
||||||
|
assert view.cls.extra_class is ExtraClass
|
||||||
|
|
||||||
|
|
||||||
class ActionDecoratorTestCase(TestCase):
|
class ActionDecoratorTestCase(TestCase):
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user