2012-03-21 64 views
10

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

  1. 逐个验证请求数据和警戒异常。如果发生错误,请提出Http404或其他异常以明确宣布发生错误。或者
  2. 只是编写没有异常处理的代码,并假设它会工作。如果有什么不好的事情发生,未捕获的异常会导致内部服务器错误,这仍然是浏览器

对于我的错误,最前一页方法似乎更正统,因为在Python的“哲学明确优于隐含“真的很重要。但是,由于各种异常检查都从第二个中删除,所以它更干净,更少碎片化,更具可读性。

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

  1. 两种方法都可以接受吗?
  2. 对于其他Javascript库,第二种方法会失败吗?
  3. 这是什么最佳做法?

PS。我确实做了重要的数据验证。请不要为此抛弃话题。 :)

+0

你应该标记其中一个答案是正确的,并且赞扬那些帮助你的答案。这是一个很好的习惯,如果你打算继续使用这个网站,并给那些花时间回答你的人一个好姿态:) – Sid 2012-03-21 11:38:29

+0

@Sid谢谢你的指导:)。我想我的问题还没有完成答案(但我现在已经选择了最好的答案)。真的很抱歉,但是我的名声还不足以让您满意。 – kavinyao 2012-03-21 12:35:59

+0

如果您的问题未得到完全解答,您无需选择最佳答案。对不起并不意味着要冲你:) – Sid 2012-03-21 12:50:26

回答

17

如果返回用4XX或者5XX状态码的响应,这是一个错误,将触发jQueries error处理。虽然它肯定是可能的每一个时间和JSON响应使用“错误”字段(如由dm03514建议)简单的返回状态200这是不好的原因有两个:

  1. 它违背了良好的HTTP做法。还有一个原因为什么有很多的错误代码定义

  2. 您不能使用jQuery的已经有一个错误处理程序,可以让你从错误处理单独的普通行为的事实。

大部分时间的错误响应将从无差错响应非常不同所以它根本没有意义,把这个消息的处理为一体的JS代码。因此,总结一下,使用状态为200的JSON响应作为您的正常响应,并返回一个(适当的!)4xx/5xx响应错误。这些也可以携带JSON负载,因此您的服务器端可以添加有关错误的其他详细信息。

+0

真的很感谢你的澄清。所以实际上,我应该使用'HttpResponse'的子类,例如'HttpResponseNotFound',通知浏览器端发生了不好的事情,并按预期触发'error'处理程序,对吧? – kavinyao 2012-03-21 07:51:39

0

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

  • 无效或缺少PARAMS
  • 高级别的错误,如用户名已经存在于数据库(在例如注册情况)
  • 所有其他系统错误

我想如果你分类你的错误,因为一些特殊的错误,用户必须知道,然后一切那么你的代码将有最多2或3错误返回路线,这恕我直言”不是个不好。 我使用JSON返回错误,我的结构通常是这样的:

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

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

希望这会有所帮助。

+0

阅读答案后,我明白达到同样的效果并不能证明我的方法(第二个)。谢谢! – kavinyao 2012-03-21 05:18:31

0

我不会采取任何建议的方法。我会根据西德所说的话提出一些建议。你为什么不想写无错代码?

我会尽力解决所有可能的错误和我在任何时候编写的代码中的错误。这包括验证用户输入。用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回调确认的响应是有效的,如果它不提醒的是什么,他们做错了用户。不要让他们挂你正在为他们做一个应用程序!

+0

我明白你的观点。但是,是否有任何_explicit_方法来触发jQuery.ajax的错误参数?我想当请求真正成功时,会调用成功的参数。 – kavinyao 2012-03-21 05:28:17

0

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

例子:

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

方案2是不是一个好的做法,因为当有未捕获的异常,是由服务器抛出和一般内部服务器错误发生的情况是未知的程序员。

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

+0

感谢您的建议。但是如果我像例子中那样返回HttpResponse,那么jQuery.ajax的成功函数会被调用,对吧?我只是想知道错误的功能是什么? – kavinyao 2012-03-21 05:06:28

+0

是的,成功函数将被调用。在JQuery [文档](http://api.jquery.com/jQuery.ajax/)中说:**错误回调被调用,按照它们被注册的顺序,如果请求失败。**,那么只有错误处理程序将在请求发生错误而不是请求中发送的信息时触发。 – 2012-03-21 14:24:31

1

我认为:

  1. 第二种方法是不能接受的。
  2. 它不会失败,因为服务器仍然会发送一个http响应。
  3. 让我告诉你我做什么在我的项目:
我的项目启动时

,我总是预先添加的文件夹结构的顶部命名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 === 当谈到如何应对阿贾克斯相应的响应,你可以使用新功能在jquery1.5 statusCode:从jQuery文档

$.ajax({ 
    statusCode: { 
    404: function() { 
     alert('page not found'); 
    } 
    } 
}); 

当 响应具有相应的代码时要调用的数字HTTP代码和函数的映射。例如,下面将 警报时响应状态是404

+0

感谢您的解决方案。对常见错误进行分类并使用中间件处理它们似乎是一种整洁且可扩展的解决方案。这种方法常用吗? – kavinyao 2012-03-21 05:13:31

+0

那么,设计你的自定义异常是一个建议的方式来写作强大的程序,至于Django,我不确定这是否是最好的解决方案,因为我没有使用它的时期。但是Django仍然是python,如果你认为这种方法是pythonic,它就会起作用。 – Reorx 2012-03-21 05:51:23