Как отключить возврат страницы ошибок HTML с помощью рамки django rest?

Если у меня есть ошибка за пределами libs DRF, django отправляет HTML-код ошибки вместо правильного использования ответа ошибки DRF.

Например:

@api_view(['POST'])
@permission_classes((IsAuthenticated,))
def downloadData(request):
    print request.POST['tables']

Возвращает исключение MultiValueDictKeyError: "'tables'". И верните полный HTML. Как получить только ошибку JSON?

P.D:

Это окончательный код:

@api_view(['GET', 'POST'])
def process_exception(request, exception):
    # response = json.dumps({'status': status.HTTP_500_INTERNAL_SERVER_ERROR,
    #                        'message': str(exception)})
    # return HttpResponse(response,
    #                     content_type='application/json; charset=utf-8')
    return Response({
        'error': True,
        'content': unicode(exception)},
        status=status.HTTP_500_INTERNAL_SERVER_ERROR
    )


class ExceptionMiddleware(object):
    def process_exception(self, request, exception):
        # response = json.dumps({'status': status.HTTP_500_INTERNAL_SERVER_ERROR,
        #                        'message': str(exception)})
        # return HttpResponse(response,
        #                     content_type='application/json; charset=utf-8')
        print exception
        return process_exception(request, exception)

Ответ 1

Одним из способов возврата json было бы уловить исключения и вернуть правильный ответ (если вы используете JSONParser в качестве парсера по умолчанию):

from rest_framework.response import Response
from rest_framework import status


@api_view(['POST'])
@permission_classes((IsAuthenticated,))
def downloadData(request):
    try:
        print request.POST['tables']
    except:
        return Response({'error': True, 'content': 'Exception!'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    return Response({'error': False})

UPDATE

Для глобального разумного варианта использования правильная идея заключается в том, чтобы поставить ответ json в промежуточное программное обеспечение исключения.

Вы можете найти пример в этом сообщении в блоге.

В вашем случае вам нужно вернуть ответ DRF, поэтому, если какое-либо исключение будет поднято, оно закончится в process_exception:

from rest_framework.response import Response


class ExceptionMiddleware(object):

    def process_exception(self, request, exception):
        return Response({'error': True, 'content': exception}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

Ответ 2

Вы можете заменить обработчики ошибок по умолчанию, указав настраиваемый обработчик в URLConf как описано здесь.

Что-то вроде этого:

# In urls.py
handler500 = 'my_app.views.api_500'

и:

# In my_app.views
def api_500(request):
    response = HttpResponse('{"detail":"An Error Occurred"}', content_type="application/json", status=500)
    return response

Я надеюсь, что это поможет.

Ответ 3

Как вы можете видеть в документации.

Все, что вам нужно сделать, это настроить параметры.

REST_FRAMEWORK = {
   'DEFAULT_AUTHENTICATION_CLASSES': (
       'rest_framework.authentication.TokenAuthentication',
       'rest_framework.parsers.JSONParser',
    ),
    'EXCEPTION_HANDLER': 'core.views.api_500_handler',
}

И указывая на представление, которое получит (exception, context)

Вот так:

from rest_framework.views import exception_handler
...
def api_500_handler(exception, context):
    response = exception_handler(exception, context)
    try:
        detail = response.data['detail']
    except AttributeError:
        detail = exception.message
    response = HttpResponse(
        json.dumps({'detail': detail}),
        content_type="application/json", status=500
    )
    return response

Моя реализация подобна этому, потому что, если возникает ожидаемое исключение рамки ожидания, например, 'exceptions.NotFound', exception.message будет пустой. Вот почему я впервые позвонил в exception_handler рамки отдыха. Если это ожидаемое исключение, я получу его сообщение.