且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Django Rest框架 - 处理API参数验证错误的***方式?

更新时间:2023-02-20 12:00:53

Django REST框架内部处理错误,一般来说,成为可以由客户解析的合理回应。这是由内部异常处理完成的扩展为特殊情况。



通常当您遇到指定不存在的对象的情况下,您提出一个 404未找到错误。 Django实际上有一个帮手,称为 get_object_or_404 ,因为它往往是一个很常见的逻辑,特别是在API。 Django REST框架将转换此引发的 Http404 错误,并将其转换为具有404 HTTP错误代码的以下响应。

  {
detail:未找到
}

现在,此格式(和具有详细信息键的对象)不仅限于 Http404 错误,它适用于由Django REST框架提供的任何子类 APIError 的错误。



所以在你的例子中,你可以通过执行

  ex = APIError(Section not found)
ex.status_code = 404

raise ex

或使用 get_object_or_404 并让Django REST框架处理它

  from django.shortcuts import get_object_or_404 
section = get_object_or_404(Section.objects,pk = 1234)

当然你还可以覆盖异常手要将这些错误格式化到你想要的格式。

  def exception_handler(exc):
from django.http import Http404
从rest_framework导入状态

exc_data = {
errors:[],
}

如果isinstance(exc,Http404):
exc_data [errors]。append({
message:对不起,该页面不存在,
code:404,
})
else if isinstance(exc.detail,list):
在exc.detail中的消息:
exc_data [errors]。append({
message:message,
code:exc.status_code,
}
else:
exc_data [errors]。append({
message:exc.detail,
code:exc.status_code,
})

返回响应(exc_data,status = status.HTTP_200_OK)

请注意,这将给出所有错误回复状态码为200,并将实际的HTTP状态代码嵌入正文。这对于某些应用程序非常有用,但通常建议仅使用200状态代码进行成功响应。


What would be an efficient way to construct error messages during HTTP request parameter validation and serialize them?

Currently, as I have it:

except Section.DoesNotExist:
            return Response(headers = {'INTERNAL_MSG': 'SECTION_NOT_FOUND',
                                       'INTERNAL_CODE': '400'},
                            status = status.HTTP_200_OK)

But, it seems to me this is a not a good way to do it, since I am injecting internal error messages into the HTTP protocol that have nothing to do with HTTP topology.

Preferably, I would like to do something like Twitter, Facebook, and others are doing in their APIs:

{"errors":[{"message":"Sorry, that page does not exist","code":34}]}

So, could you please share your approach to dealing with errors and returning them?

Very much appreciated, thanks!

Django REST framework handles errors internally and in general does a pretty good job of converting them into reasonable responses that can be parsed by clients. This is done by the internal exception handling, which is open to being extended for special cases.

Usually when you run into a case where an object was specified that does not exist, you raise a 404 Not Found error. Django actually has a helper for this, called get_object_or_404, as it tends to be a very common bit of logic, especially in APIs. Django REST framework will convert this Http404 error that is raised and convert it in to the following response that has a 404 HTTP error code.

{
  "detail": "Not found"
}

Now, this format (and object with a detail key) is not restricted to only Http404 errors, it works for any error that subclasses APIError provided by Django REST framework.

So in your example, you could raise a similar exception by doing

ex = APIError("Section not found")
ex.status_code = 404

raise ex

Or by using get_object_or_404 and letting Django REST framework handle it

from django.shortcuts import get_object_or_404
section = get_object_or_404(Section.objects, pk=1234)

Of course, you can still override the exception handler to format these errors how you want.

def exception_handler(exc):
    from django.http import Http404
    from rest_framework import status

    exc_data = {
        "errors": [],
    }

    if isinstance(exc, Http404):
        exc_data["errors"].append({
            "message": "Sorry that page does not exist",
            "code": 404,
        })
    else if isinstance(exc.detail, list):
        for message in exc.detail:
            exc_data["errors"].append({
                "message": message,
                "code": exc.status_code,
            }
    else:
        exc_data["errors"].append({
            "message": exc.detail,
            "code": exc.status_code,
        })

    return Response(exc_data, status=status.HTTP_200_OK)

Note that this will give all error responses a status code of 200, and embed the actual HTTP status code within the body. This is useful for some applications, but it is usually recommended to only use the 200 status code for success responses.