如何使用 django rest 框架禁用 HTML 错误页面的返回?

Posted

技术标签:

【中文标题】如何使用 django rest 框架禁用 HTML 错误页面的返回?【英文标题】:How disable return of HTML error page with django rest framework? 【发布时间】:2014-02-01 18:21:36 【问题描述】:

如果我在 DRF 的库之外有错误,django 会发回错误的 html,而不是 DRF 使用的正确错误响应。

例如:

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

返回异常MultiValueDictKeyError: "'tables'"。并取回完整的 HTML。如何只获取 JSON 的错误?

警察局:

这是最终代码:

@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)

更新

对于全局明智的用例,正确的想法是将 json 响应放入 exception middleware。

您可以在this blog post 中找到示例。

在您的情况下,您需要返回 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)

【讨论】:

是的,但是需要修补每个视图。我想知道是否存在可以在全球范围内使用的东西 @mamcx 我已经更新了我的答案。请看一看。 很好,@mariodev。 DRF 应该包括这一点,JSON API 返回 HTML 的形式很糟糕。也许你应该提交它? ;-)【参考方案2】:

您可以通过在 URLConf as documented here 中指定自定义处理程序来替换默认错误处理程序

类似这样的:

# 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】:

正如您在documentation 中看到的那样。

您需要做的就是配置设置。

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。如果是预期的异常,我会收到它的消息。

【讨论】:

EXCEPTION_HANDLER 键应用作全局的、包罗万象的错误处理程序,但您可以在此处检查异常以查看它们返回所需响应的类型

以上是关于如何使用 django rest 框架禁用 HTML 错误页面的返回?的主要内容,如果未能解决你的问题,请参考以下文章

Django/Django Rest 框架 - 禁用 CSRF

如何忽略发送到 Django REST 框架的 CSRF 令牌?

如何使用迁移框架添加 Django REST 框架身份验证令牌

如何在 Django REST 框架中使用事务?

如何在 django rest 框架中访问获取请求数据

如何在带有 Django Rest 框架的 React 前端使用 Django 用户组和权限