django-rest-framework/rest_framework/decorators.py

54 lines
1.9 KiB
Python

from functools import wraps
from django.http import Http404
from django.utils.decorators import available_attrs
from django.core.exceptions import PermissionDenied
from rest_framework import exceptions
from rest_framework import status
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.settings import api_settings
def api_view(allowed_methods):
"""
Decorator for function based views.
@api_view(['GET', 'POST'])
def my_view(request):
# request will be an instance of `Request`
# `Response` objects will have .request set automatically
# APIException instances will be handled
"""
allowed_methods = [method.upper() for method in allowed_methods]
def decorator(func):
@wraps(func, assigned=available_attrs(func))
def inner(request, *args, **kwargs):
try:
request = Request(request)
if request.method not in allowed_methods:
raise exceptions.MethodNotAllowed(request.method)
response = func(request, *args, **kwargs)
if isinstance(response, Response):
response.request = request
if api_settings.FORMAT_SUFFIX_KWARG:
response.format = kwargs.get(api_settings.FORMAT_SUFFIX_KWARG, None)
return response
except exceptions.APIException as exc:
return Response({'detail': exc.detail}, status=exc.status_code)
except Http404 as exc:
return Response({'detail': 'Not found'},
status=status.HTTP_404_NOT_FOUND)
except PermissionDenied as exc:
return Response({'detail': 'Permission denied'},
status=status.HTTP_403_FORBIDDEN)
return inner
return decorator