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

时间:2022-11-08 00:19:00

I am putting together an API with Django Rest Framework. I want to customise my error handling. I read quite a bit (link1, link2, link3) about custom error handling but can't find something that suits my needs.

我正在将一个API与Django Rest Framework放在一起。我想自定义我的错误处理。我读了很多关于自定义错误处理的内容(link1,link2,link3),但找不到适合我需要的东西。

Basically, I'd like to change the structure of my error messages to get something like this :

基本上,我想改变我的错误消息的结构,得到这样的东西:

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

Instead of :

代替 :

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

I already have a custom ExceptionMiddleware to catch the 500 errors and return a JSON, but I have no power on all the other errors.

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

Code of the ExceptionMiddleware:

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)

From Django doc :

来自Django doc:

Note that the exception handler will only be called for responses generated by raised exceptions. It will not be used for any responses returned directly by the view, such as the HTTP_400_BAD_REQUEST responses that are returned by the generic views when serializer validation fails.

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

This is exactly what I am trying to achieve, customise those 400 errors.

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

Thanks a lot,

非常感谢,

4 个解决方案

#1


1  

The exception handler is indeed what you're looking for. The current mixing do raise an exception in case of failed validation (https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/mixins.py).

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

Note that the exception handler will only be called for responses generated by raised exceptions. It will not be used for any responses returned directly by the view, such as the HTTP_400_BAD_REQUEST responses that are returned by the generic views when serializer validation fails.

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

I think this part doesn't hold any longer and should be rephrased by removing the "generic" word.

我认为这一部分不再存在,应该通过删除“通用”一词来改写。

#2


1  

This is my custom exception handler:

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

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)

It represents APIException errors in a format like this:

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

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

Django Rest Framework reference documentation:
http://www.django-rest-framework.org/api-guide/exceptions/#custom-exception-handling

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

#3


0  

Alright so based on Linovia's answer, here is my custom handler :

好吧基于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

#4


0  

I know this is a bit late, (better late than never).

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

If you have a structured error message, then try this by inheriting the Exception class

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

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

and the usage will be like this:

用法如下:

if some_condition:
    error_msg = {
        "error": True,
        "errors": [
            {
                "message": "Field %s does not exist"%('my_test_field'),
                "code": 1050
            }
        ]
    }
    raise CustomAPIException(error_msg)

Reference : How to override exception messages in django rest framework

参考:如何在django rest框架中覆盖异常消息

#1


1  

The exception handler is indeed what you're looking for. The current mixing do raise an exception in case of failed validation (https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/mixins.py).

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

Note that the exception handler will only be called for responses generated by raised exceptions. It will not be used for any responses returned directly by the view, such as the HTTP_400_BAD_REQUEST responses that are returned by the generic views when serializer validation fails.

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

I think this part doesn't hold any longer and should be rephrased by removing the "generic" word.

我认为这一部分不再存在,应该通过删除“通用”一词来改写。

#2


1  

This is my custom exception handler:

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

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)

It represents APIException errors in a format like this:

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

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

Django Rest Framework reference documentation:
http://www.django-rest-framework.org/api-guide/exceptions/#custom-exception-handling

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

#3


0  

Alright so based on Linovia's answer, here is my custom handler :

好吧基于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

#4


0  

I know this is a bit late, (better late than never).

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

If you have a structured error message, then try this by inheriting the Exception class

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

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

and the usage will be like this:

用法如下:

if some_condition:
    error_msg = {
        "error": True,
        "errors": [
            {
                "message": "Field %s does not exist"%('my_test_field'),
                "code": 1050
            }
        ]
    }
    raise CustomAPIException(error_msg)

Reference : How to override exception messages in django rest framework

参考:如何在django rest框架中覆盖异常消息