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

Если у меня есть ошибка за пределами библиотек 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)

person mamcx    schedule 13.01.2014    source источник


Ответы (3)


Один из способов вернуть 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})

ОБНОВЛЕНИЕ

Для глобального разумного варианта использования правильной идеей было бы поместить ответ 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)
person mariodev    schedule 13.01.2014
comment
Да, но это требует патча для каждого представления. Интересно, существует ли что-то, что можно было бы использовать глобально - person mamcx; 14.01.2014
comment
@mamcx Я обновил свой ответ. Пожалуйста, взгляните. - person mariodev; 15.01.2014
comment
Отлично, @mariodev. DRF должен включать это, для JSON API недопустимо возвращать HTML. Может быть, вам стоит подать его? ;-) - person s29; 25.06.2015


Как видно из документации.

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

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 остальных фреймворков. Если это ожидаемое исключение, я получу его сообщение.

person Laraconda    schedule 15.09.2015
comment
ключ EXCEPTION_HANDLER следует использовать как глобальный универсальный обработчик ошибок, но вы можете проверить здесь исключения, чтобы увидеть, какого типа они должны возвращать желаемый ответ. - person OzzyTheGiant; 18.04.2019