我开始考虑在我的Django应用程序中进行适当的异常处理,我的目标是让它尽可能地对用户友好.通过用户友好性,我意味着用户必须始终得到详细的澄清,说明到底哪里出了问题.

将状态为200的JSON响应用于正常响应和

我试图用谷歌搜索这个答案中的关键词,因为我脑子里的问题仍然比答案多.

  1. How do I decide upon which error code - 400 or 500 - to return? I mean, Django has many predefined error types, and how can I implement this mapping between Django exception types and 400-500 error code to make the exception handling blocks as DRY and reusable as possible?
  2. Can the approach with middleware suggested by @Reorx in the post be considered viable ? ( The answer got only one upvote, thus making me reluctant to delve into details and implement it in my project
  3. Most importantly, sometimes I may wish to raise an error related to business logic, rather than incorrect syntax or something standard like null value. For example, if there's no CEO in my legal entity, I might want to prohibit the user from adding a contract. What should be the error status in this case, and how do I throw an error with my detailed explanation of the error for the user?

让我们从一个简单的Angular 来考虑.

def test_view (request):

   try:
          # Some code .... 
          if my_business_logic_is_violated():
              # How do I raise the error
              error_msg = "You violated bussiness logic because..."
              # How do I pass error_msg 
          my_response = {'my_field' : value}
  except ExpectedError as e:
          # what is the most appropriate way to pass both error status and custom message
          # How do I list all possible error types here (instead of ExpectedError to make the exception handling block as DRY and reusable as possible
      return JsonResponse({'status':'false','message':message}, status=500)

推荐答案

首先,您应该考虑要公开哪些错误:

  • 通常会披露4xx错误(归因于客户端的错误),以便用户可以更正请求.

  • On the other side, 5xx errors (Errors that are attributed to the server-side) are usually only presented without information. In my opinion for those you should use tools like Sentry do monitor and resolve this errors, that may have security issues embedded in them.

Having this is mind in my opinion for a correct Ajax request you should return a status code and then some json to help understand what happened like a message and an explanation (when applicable).

如果你的目标是使用ajax来提交信息,我建议将你想要的设置为form.这样你就可以轻松地通过一些验证过程.我假设例子中的情况就是这样.

First - Is the request correct?

def test_view(request):
    message = None
    explanation = None
    status_code = 500
    # First, is the request correct?
    if request.is_ajax() and request.method == "POST":
        ....
    else: 
        status_code = 400
        message = "The request is not valid."
        # You should log this error because this usually means your front end has a bug.
        # do you whant to explain anything?
        explanation = "The server could not accept your request because it was not valid. Please try again and if the error keeps happening get in contact with us."

    return JsonResponse({'message':message,'explanation':explanation}, status=status_code)

Second-表格中是否有错误?

form = TestForm(request.POST)
if form.is_valid():
    ...
else:
    message = "The form has errors"
    explanation = form.errors.as_data()
    # Also incorrect request but this time the only flag for you should be that maybe JavaScript validation can be used.
    status_code = 400

You may even get error field by field so you may presented in a better way in the form itself.

Third - Let's process the request

        try:
            test_method(form.cleaned_data)
        except `PermissionError` as e:
            status_code= 403
            message= "Your account doesn't have permissions to go so far!"
        except `Conflict` as e:
            status_code= 409
            message= "Other user is working in the same information, he got there first"
        ....
        else:
            status_code= 201
            message= "Object created with success!"

根据您定义的例外,可能需要不同的代码.go Wikipedia家查一下名单. 不要忘记,响应在代码中也会有所不同.如果向数据库中添加了某些内容,则应返回201.如果您刚刚获得信息,那么您正在寻找GET请求.

Responding to the questions

  1. Django exceptions will return 500 errors if not dealt with, because if you don't know that an exception is going to happen then it is an error in the server. With exception to 404 and login requirements I would do try catch blocks for everything. (For 404 you may raise it and if you do @login_requiredor a permission required django will respond with the appropriate code without you doing anything).

  2. I don't agree completely to the approach. As you said errors should be explicit so you should know allways what is suppose to happen and how to explain it, and make it dependable on the operation performed.

  3. 我认为400个错误就可以了.这是一个糟糕的请求,你只需要解释为什么,错误代码是为你和你的js代码,所以要保持一致

  4. (提供的示例)-在text_view中,您应该具有第三个示例中的test_method.

测试方法应具有以下 struct :

def test_method(validated_data):
    try: 
        my_business_logic_is_violated():
    catch BusinessLogicViolation:
        raise
    else:
        ... #your code

The in my example:

   try:
        test_method(form.cleaned_data)
    except `BusinessLogicViolation` as e:
        status_code= 400
        message= "You violated the business logic"
        explanation = e.explanation
   ...

我认为业务逻辑违规是一个客户端错误,因为如果在请求之前需要进行某些操作,客户端应该意识到这一点,并要求用户首先执行该操作.(来自Error Definition名):

The 400 (Bad Request) status code indicates that the server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request
message framing, or deceptive request routing).

By the way, you can see the Python Docs on User-defined Exceptions so you may give appropriate error messages. The idea behind this example is that you raise a BusinessLogicViolationexception with a different message in my_business_logic_is_violated()according to the place where it was generated.

Json相关问答推荐

Vega通孔信号中的动态梯度

使用更高级别架构中的字段值在$def内实现约束

给定一个包含两个数组的JSON输入文件,如何使用Jolt将一个数组中的每个元素与另一个数组组合在一起?

如何使用模式注册中心创建从主题中取消本地化的ks qlDB表?

在 postgres 14 中将记录转换为所需的 json 格式

添加到数组时出错:找不到Add的重载和参数计数:1

如何在循环中传递列表(会话(字符串属性))以在 Gatling Scala 中创建批量 Json 请求

如何实现一个通用的 serde_json::from_str

避免 KeyError 的默认字典键

解析包含换行符的 JSON

Jackson 没有使用 @JsonProperty 覆盖 Getter

关于使用 $ref 的 JSON 模式

使用 Node.js 对 JSON 中的字符串大小有限制吗?

如何将有向无环图 (DAG) 存储为 JSON?

使用 JSON.Net 的 C# 到 JSON 序列化

使用 Codable 序列化为 JSON 时的 Swift 字符串转义

JSON 模式 - 如果对象*不*包含特定属性则有效

如何在spark 上将json字符串转换为数据帧

SCRIPT5009:JSON未定义

Laravel 5 控制器将 JSON 整数作为字符串发送