如何向Django Rest Framework添加自定义错误代码

时间:2016-02-17 12:52:10

标签: python django exception-handling django-rest-framework

我正在将一个API与Django Rest Framework放在一起。我想自定义我的错误处理。我阅读了很多(link1link2link3)关于自定义错误处理但无法找到适合我需求的内容。

基本上,我想更改错误消息的结构以获得类似这样的内容:

{
  "error": True,
  "errors": [
    {
      "message": "Field %s does not exist",
      "code": 1050
    }
  ]
}

而不是:

{"detail":"Field does not exist"}

我已经有一个自定义的ExceptionMiddleware来捕获500个错误并返回一个JSON,但是我没有权力处理所有其他错误。

ExceptionMiddleware的代码:

class ExceptionMiddleware(object):

    def process_exception(self, request, exception):

        if request.user.is_staff:
            detail = exception.message
        else:
            detail = 'Something went wrong, please contact a staff member.'

        return HttpResponse('{"detail":"%s"}'%detail, content_type="application/json", status=500)

来自Django doc:

  

请注意,只会为响应调用异常处理程序   由引发的异常产生。它不会用于任何回复   由视图直接返回,例如HTTP_400_BAD_REQUEST   序列化程序时通用视图返回的响应   验证失败。

这正是我想要实现的,自定义这400个错误。

非常感谢,

4 个答案:

答案 0 :(得分:1)

异常处理程序确实是您正在寻找的。如果验证失败,当前混合会引发异常(https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/mixins.py)。

  

请注意,只会针对由引发的异常生成的响应调用异常处理程序。它不会用于视图直接返回的任何响应,例如当序列化程序验证失败时通用视图返回的HTTP_400_BAD_REQUEST响应。

我认为这部分不再存在,应该通过删除" generic"来改写。字。

答案 1 :(得分:1)

这是我的自定义异常处理程序:

def api_exception_handler(exception, context):

    if isinstance(exception, exceptions.APIException):

        headers = {}

        if getattr(exception, 'auth_header', None):
            headers['WWW-Authenticate'] = exception.auth_header

        if getattr(exception, 'wait', None):
            headers['Retry-After'] = '%d' % exception.wait

        data = exception.get_full_details()
        set_rollback()

        return Response(data, status=exception.status_code, headers=headers)

    return exception_handler(exception, context)

它以如下格式表示APIException错误:

{
    "field_name": [
        {
            "message": "Error message",
            "code": "error_code"
        },
        {
            "message": "Another error",
            "code": "another_error"
        }
    ]
}

Django Rest Framework参考文档:
http://www.django-rest-framework.org/api-guide/exceptions/#custom-exception-handling

答案 2 :(得分:1)

我知道这有点晚了(总比没有好)。

如果您收到结构化的错误消息,请通过继承Exception类尝试此操作

pushState

,用法如下:

from rest_framework.serializers import ValidationError
from rest_framework import status


class CustomAPIException(ValidationError):
    status_code = status.HTTP_400_BAD_REQUEST
    default_code = 'error'

    def __init__(self, detail, status_code=None):
        self.detail = detail
        if status_code is not None:
            self.status_code = status_code

参考:How to override exception messages in django rest framework

答案 3 :(得分:0)

好的,基于Linovia的回答,这是我的自定义处理程序:

def custom_exception_handler(exc, context):
    response = exception_handler(exc, context)
    if response is not None:
        errors = []
        for msg in response.data.values():
            errors.append({'message': msg[0], 'error': get_error_message()})

        response.data = {"errors": errors}

    return response