如何在CreateAPIView中引发HttpResponseForbidden

时间:2018-04-28 12:28:17

标签: django django-rest-framework

我在perform_create方法中尝试了这个:

if not user.is_active:
    return HttpResponseForbidden()

但没有发生错误,它仍然在回应201

1 个答案:

答案 0 :(得分:1)

请改用此构造:

from rest_framework.exceptions import PermissionDenied  
# You can also use Django's PermissionDenied here; DRF handles that nicely
from django.core.exceptions import PermissionDenied

if not user.is_active:
    raise PermissionDenied

PermissionDenied定义如下:

class PermissionDenied(APIException):
    status_code = status.HTTP_403_FORBIDDEN
    default_detail = _('You do not have permission to perform this action.')
    default_code = 'permission_denied'

您可能想知道如何在View内引发异常会返回相应的HttpResponse。 DRF的APIView有一个漂亮的handle_exception方法,它使用exception_handler函数(如下所示)来实现这个魔力:

def exception_handler(exc, context):
    """
    Returns the response that should be used for any given exception.

    By default we handle the REST framework `APIException`, and also
    Django's built-in `Http404` and `PermissionDenied` exceptions.

    Any unhandled exceptions may return `None`, which will cause a 500 error
    to be raised.
    """
    if isinstance(exc, Http404):
        exc = exceptions.NotFound()
    # This is how both PermissionDenied classes are made to work
    elif isinstance(exc, PermissionDenied):  
        exc = exceptions.PermissionDenied()

    if isinstance(exc, exceptions.APIException):
        headers = {}
        if getattr(exc, 'auth_header', None):
            headers['WWW-Authenticate'] = exc.auth_header
        if getattr(exc, 'wait', None):
            headers['Retry-After'] = '%d' % exc.wait

        if isinstance(exc.detail, (list, dict)):
            data = exc.detail
        else:
            data = {'detail': exc.detail}

        set_rollback()
        return Response(data, status=exc.status_code, headers=headers)

    return None

澄清:

PermissionDenied是一个例外;您需要raise而不是return