mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-22 09:36:49 +03:00
0552810410
Set literals are available on all supported Python versions. They are idiomatic and always faster: $ python3 -m timeit '{}' 10000000 loops, best of 3: 0.0357 usec per loop $ python3 -m timeit 'dict()' 10000000 loops, best of 3: 0.104 usec per loop $ python3 -m timeit '{1, 2, 3}' 10000000 loops, best of 3: 0.0754 usec per loop $ python3 -m timeit 'set([1, 2, 3])' 1000000 loops, best of 3: 0.228 usec per loop
159 lines
5.0 KiB
Python
159 lines
5.0 KiB
Python
"""
|
|
The most important decorator in this module is `@api_view`, which is used
|
|
for writing function-based views with REST framework.
|
|
|
|
There are also various decorators for setting the API policies on function
|
|
based views, as well as the `@detail_route` and `@list_route` decorators, which are
|
|
used to annotate methods on viewsets that should be included by routers.
|
|
"""
|
|
from __future__ import unicode_literals
|
|
|
|
import types
|
|
import warnings
|
|
|
|
from django.utils import six
|
|
|
|
from rest_framework.views import APIView
|
|
|
|
|
|
def api_view(http_method_names=None, exclude_from_schema=False):
|
|
"""
|
|
Decorator that converts a function-based view into an APIView subclass.
|
|
Takes a list of allowed methods for the view as an argument.
|
|
"""
|
|
http_method_names = ['GET'] if (http_method_names is None) else http_method_names
|
|
|
|
def decorator(func):
|
|
|
|
WrappedAPIView = type(
|
|
six.PY3 and 'WrappedAPIView' or b'WrappedAPIView',
|
|
(APIView,),
|
|
{'__doc__': func.__doc__}
|
|
)
|
|
|
|
# Note, the above allows us to set the docstring.
|
|
# It is the equivalent of:
|
|
#
|
|
# class WrappedAPIView(APIView):
|
|
# pass
|
|
# WrappedAPIView.__doc__ = func.doc <--- Not possible to do this
|
|
|
|
# api_view applied without (method_names)
|
|
assert not(isinstance(http_method_names, types.FunctionType)), \
|
|
'@api_view missing list of allowed HTTP methods'
|
|
|
|
# api_view applied with eg. string instead of list of strings
|
|
assert isinstance(http_method_names, (list, tuple)), \
|
|
'@api_view expected a list of strings, received %s' % type(http_method_names).__name__
|
|
|
|
allowed_methods = set(http_method_names) | {'options'}
|
|
WrappedAPIView.http_method_names = [method.lower() for method in allowed_methods]
|
|
|
|
def handler(self, *args, **kwargs):
|
|
return func(*args, **kwargs)
|
|
|
|
for method in http_method_names:
|
|
setattr(WrappedAPIView, method.lower(), handler)
|
|
|
|
WrappedAPIView.__name__ = func.__name__
|
|
WrappedAPIView.__module__ = func.__module__
|
|
|
|
WrappedAPIView.renderer_classes = getattr(func, 'renderer_classes',
|
|
APIView.renderer_classes)
|
|
|
|
WrappedAPIView.parser_classes = getattr(func, 'parser_classes',
|
|
APIView.parser_classes)
|
|
|
|
WrappedAPIView.authentication_classes = getattr(func, 'authentication_classes',
|
|
APIView.authentication_classes)
|
|
|
|
WrappedAPIView.throttle_classes = getattr(func, 'throttle_classes',
|
|
APIView.throttle_classes)
|
|
|
|
WrappedAPIView.permission_classes = getattr(func, 'permission_classes',
|
|
APIView.permission_classes)
|
|
|
|
WrappedAPIView.schema = getattr(func, 'schema',
|
|
APIView.schema)
|
|
|
|
if exclude_from_schema:
|
|
warnings.warn(
|
|
"The `exclude_from_schema` argument to `api_view` is pending deprecation. "
|
|
"Use the `schema` decorator instead, passing `None`.",
|
|
PendingDeprecationWarning
|
|
)
|
|
WrappedAPIView.exclude_from_schema = exclude_from_schema
|
|
|
|
return WrappedAPIView.as_view()
|
|
return decorator
|
|
|
|
|
|
def renderer_classes(renderer_classes):
|
|
def decorator(func):
|
|
func.renderer_classes = renderer_classes
|
|
return func
|
|
return decorator
|
|
|
|
|
|
def parser_classes(parser_classes):
|
|
def decorator(func):
|
|
func.parser_classes = parser_classes
|
|
return func
|
|
return decorator
|
|
|
|
|
|
def authentication_classes(authentication_classes):
|
|
def decorator(func):
|
|
func.authentication_classes = authentication_classes
|
|
return func
|
|
return decorator
|
|
|
|
|
|
def throttle_classes(throttle_classes):
|
|
def decorator(func):
|
|
func.throttle_classes = throttle_classes
|
|
return func
|
|
return decorator
|
|
|
|
|
|
def permission_classes(permission_classes):
|
|
def decorator(func):
|
|
func.permission_classes = permission_classes
|
|
return func
|
|
return decorator
|
|
|
|
|
|
def schema(view_inspector):
|
|
def decorator(func):
|
|
func.schema = view_inspector
|
|
return func
|
|
return decorator
|
|
|
|
|
|
def detail_route(methods=None, **kwargs):
|
|
"""
|
|
Used to mark a method on a ViewSet that should be routed for detail requests.
|
|
"""
|
|
methods = ['get'] if (methods is None) else methods
|
|
|
|
def decorator(func):
|
|
func.bind_to_methods = methods
|
|
func.detail = True
|
|
func.kwargs = kwargs
|
|
return func
|
|
return decorator
|
|
|
|
|
|
def list_route(methods=None, **kwargs):
|
|
"""
|
|
Used to mark a method on a ViewSet that should be routed for list requests.
|
|
"""
|
|
methods = ['get'] if (methods is None) else methods
|
|
|
|
def decorator(func):
|
|
func.bind_to_methods = methods
|
|
func.detail = False
|
|
func.kwargs = kwargs
|
|
return func
|
|
return decorator
|