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!"})
|
||||
|
||||
|
||||
## 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
|
||||
[cite2]: http://www.boredomandlaziness.org/2012/05/djangos-cbvs-are-not-mistake-but.html
|
||||
[settings]: settings.md
|
||||
|
|
|
@ -72,6 +72,11 @@ def api_view(http_method_names=None):
|
|||
|
||||
WrappedAPIView.schema = getattr(func, '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()
|
||||
|
||||
|
@ -120,6 +125,15 @@ def schema(view_inspector):
|
|||
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):
|
||||
"""
|
||||
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.authentication import BasicAuthentication
|
||||
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
|
||||
)
|
||||
from rest_framework.parsers import JSONParser
|
||||
|
@ -166,6 +166,25 @@ class DecoratorTestCase(TestCase):
|
|||
|
||||
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):
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user