mirror of
				https://github.com/encode/django-rest-framework.git
				synced 2025-10-30 07:27:46 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			139 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			139 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
 |