Django ajax错误响应最佳实践

时间:2012-03-21 01:02:04

标签: jquery python ajax django

我正在使用ajax来改善我的Django项目的用户体验。我在这里关注的是如何正确地响应浏览器错误。据我所知,我可以:

  1. 逐个验证请求数据并逐个保护异常。如果发生了不好的事情,请提高Http404或其他异常以明确宣布发生错误。或
  2. 只需编写代码而无需异常处理,并假设它可以正常工作。如果发生了不好的事情,未捕获的异常将导致内部服务器错误,这仍然是浏览器的错误
  3. 对我来说,fisrt方法似乎更正统,因为在Python中,“明确比隐含更好”的哲学确实很重要。但是,由于从第二个中删除了各种异常检查,因此它更清晰,更少碎片,更易读。

    我正在使用jQuery来处理ajax请求/响应,这两种方法似乎都有效。我的问题是:

    1. 这两种方法都可以接受吗?
    2. 其他Javascript库的第二种方法是否会失败?
    3. 最佳做法是什么?
    4. PS。我做了必要的数据验证。请不要为此偏离主题。 :)

5 个答案:

答案 0 :(得分:17)

如果您返回状态代码为4xx或5xx的响应,则这是一个错误,将触发jQueries error处理程序。虽然每次都可以简单地返回状态200并在JSON响应中使用“错误”字段(如dm03514所示),但这有两个原因:

  1. 它违反了良好的HTTP惯例。有一个原因为什么定义了大量的错误代码

  2. 你不能使用jQuery已经有一个错误处理程序的事实,它允许你将正常行为与错误处理分开。

  3. 大多数情况下,错误响应与非错误响应有很大不同所以将这些消息的处理放在一个JS代码中是没有意义的。因此,总而言之,使用状态为200的JSON响应作为正常响应,并返回(适当的!)4xx / 5xx响应以查找错误。这些也可以携带JSON有效负载,因此您的服务器端可以添加有关错误的其他详细信息。

答案 1 :(得分:1)

在我看来:

  1. 第二种方法是不可接受的。
  2. 它不会失败,因为服务器仍会发出http响应。
  3. 让我告诉你我在项目中做了些什么:
  4. 当我的项目开始时,我总是在文件夹结构的顶部预先添加一个名为errors的模块,首先,我将编写一个继承自Exception的基本Exception类,然后写出一些常见的根据我的经验,例如ObjectNotFoundValidationError等异常类。当我认为应该在我的代码中引发异常时,我将使用此模块中的异常,当我发现需要处理新的异常时,我将在其中编写一个新的异常。

    然后是如何处理它们的工作。当您使用Django时,很容易通过中间件捕获异常,您可以编写如下内容:

    from youproject import errors
    
    # categorize your exceptions
    400_ERRORS = (errors.ValidationError, errors.ParametersMissing, )
    403_ERRORS = (errors.AuthenticationError, )
    404_ERRORS = (errors.ObjectNotFound, errors.ResourceNotExist, )
    
    class ExceptionHandleMiddleware(object):
        def process_exception(self, request, e):
            # set status_code by category of the exception you caught
            if isinstance(e, 400_ERRORS):
                status_code = 400
            elif isinstance(e, 403_ERRORS):
                status_code = 403
            elif isinstance(e, 404_ERRORS):
                status_code = 404
            else:
                # if the exception not belone to any one you expected,
                # or you just want the response to be 500
                status_code = 500
                # you can do something like write an error log or send report mail here
                logging.error(e)
    
            response_dict = {
                'status': 'error',
                # the format of error message determined by you base exception class
                'msg': str(e)
            }
            if settings.debug:
                # you can even get the traceback infomation when you are in debug mode
                response_dict['traceback'] = traceback.format_exc()
    
            # set header and return the response
            ....
    

    上面的代码是我在项目中如何处理异常处理的摘要,一般来说,它是关于准确的异常控制,正确的异常分类,当然还有“明确优于隐式”的哲学。

    === UPDATE === 在如何处理ajax中的相应响应时,您可以使用jquery1.5 statusCode中的新功能:

    $.ajax({
      statusCode: {
        404: function() {
          alert('page not found');
        }
      }
    });
    
    来自jquery文档的

      

    数字HTTP代码和函数的映射   响应有相应的代码。例如,以下将   响应状态为404

    时发出警报

答案 2 :(得分:0)

我无法回答这两种方法是否可以接受,但只能告诉你我做了什么。在我看来,我捕获了一些特定/显式错误,例如:

  • 帖子中的参数无效或缺失
  • 高级错误,例如用户名已存在于数据库中(例如,在注册情况下)
  • 所有其他系统错误

我认为如果您将错误归类为用户必须知道的某些特定错误,然后是其他所有错误,那么您的代码最多会返回2或3个错误路由,恕我直言并非如此糟糕。 我使用JSON返回错误,我的结构通常是这样的:

respons={}
response["error|ok"]
response["msg"]="User not found"
response["type"]=ERROR_TYPE # only applicable for errors

显然这是非常基本的,但希望能给你一个大致的想法。我建议不要让用户看到系统生成的内部服务器错误。即使对于内部应用程序,这也是一种糟糕的用户体验。

希望这有帮助。

答案 3 :(得分:0)

我不会采用您建议的方法。我会建议Sid说的话。你为什么不想编写无错误的代码?

我会尝试在我写的代码中始终解决所有可能的错误和错误。这包括验证用户输入。使用ajax我认为将消息发送回用户很重要。这可以通过json轻松完成。

response_dict = {}
try:
   # do action that could cause an error
except ExpectedError as e:
   response_dict['success'] = False
   response_dict['message'] e.msg # or custom message
   return HttpResponse(json.dumps(repsonse_dict))

然后在你的ajax回调中确保响应有效,如果它不警告用户他们做错了什么。不要让他们挂起你正在为他们制作应用程序!

答案 4 :(得分:0)

使用选项1但不完全按照您描述的方式,您应该返回一个带有status_code 200的HttpResponse,在响应内容中指示(使用JSON或某些文本)发生验证错误,然后,当您处理响应时使用JQuery的客户端只需检查响应内容并检测是否存在验证错误。

HttpResponse的JSON字符串示例:

{"errors": "true", "messages": ["Error #1", "Error #2", "etc."]}

选项2不是一个好的做法,因为当服务器抛出一个未捕获的异常时会发生内部服务器错误,程序员通常不知道。

不要使用HTTP状态代码来表示验证错误,这不是它们的目的。