2012-03-21 116 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