mirror of
				https://github.com/encode/django-rest-framework.git
				synced 2025-11-04 09:57:55 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			140 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			140 lines
		
	
	
		
			4.3 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
 | 
						|
 | 
						|
from django.utils import six
 | 
						|
 | 
						|
from rest_framework.views import APIView
 | 
						|
 | 
						|
 | 
						|
def api_view(http_method_names=None):
 | 
						|
 | 
						|
    """
 | 
						|
    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) | set(('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.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)
 | 
						|
 | 
						|
        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 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
 |