天天看點

關于django中間件使用的踩坑經曆背景起因詳細設計遇到的問題總結

  這個之前本地寫的那個django測試項目說起,那時候寫了個練手的項目,目的是為了熟悉總結django2.0和django1.8的差別。不試不知道,一試就發現了許許多多的坑以及bug,把這些坑以及bug解決完了之後,打算寫篇文章記錄下我遇到的問題以及解決方法和思路。
  起因是當我在自強學堂的django課堂上,看到了有一個demo,這個demo具體實作的效果就是當網站在正式環境上運作的時候,為了安全起見,将debug改為false(關閉調試模式),但是導緻網站發生錯誤無法檢視錯誤詳情。   是以demo主要的就是寫一個通過中間件識别身份的方式,如果是管理者則可以看到網站錯誤詳情,如果是普通通路者或者遊客則傳回的是簡單的錯誤碼。
 中間件識别登入身份,判斷是否為管理者,如果是管理者的話,當網站出現錯誤的時候則會顯示錯誤詳情;如果是普通遊客的話則單純顯示錯誤碼,不顯示詳情。
 我整理了一下有關django的中間件知識,這裡大概聊一下,以後有機會單獨的寫篇文章總結一下。首先我們要明白什麼是中間件: 這裡先引用官方文檔的一段話: middleware is a framework of hooks into django’s request/response processing. it’s a light, low-level “plugin” system for globally altering django’s input or output. 簡而言之,middleware就是能夠修改django中response/request對象的鈎子,我們可以利用middleware來實作在請求到達view視圖函數前的一些操作。 舉個最簡單的例子:一個管理背景判斷使用者是否登入,就是判斷request對象中的使用者,如果對象中的使用者是不存在的,則重定向到登入頁面。
大概了解了一下中間件是什麼東西,可以用來做什麼,我們大緻分析一下中間件的處理流程。
關于django中間件使用的踩坑經曆背景起因詳細設計遇到的問題總結
 相信上圖在很多django教程中看到過,上圖都是django中内置的一些中間件,這些中間件都放在django中settings.py檔案中的middleware_classes。(django 2.0版本後放在middlewares上)  然後在http請求階段,在view調用之前了,django會将middleware_classes中的中間件都執行一遍。而這裡面的主要的幾個鈎子函數: process_request()、process_view()會從上到下挨個執行一遍; process_exception()、process_template_response()、process_response()則會從下到上挨個執行一遍。  具體這幾個函數作用,以及django内置中間件分别負責什麼作用單獨會另外寫篇文章總結。  這裡的主要使用到process_exception()鈎子,這個鈎子函數隻有當view抛出異常的時候會觸發,是以很适合傳回網站的錯誤詳情。
終于到實操環節了,思路上面提到過了,這裡具體代碼實作的邏輯: 使用者通過登入界面登入到平台,通過内置的auth子產品儲存使用者登入到會話中。 如果網站出現錯誤資訊時,這時異常抛到自己的中間件時,捕獲views視圖函數抛出的異常,判斷request中的user對象是否為超級管理者,如果是的話,則傳回一個錯誤詳細響應到前端,不是的話正常傳回500錯誤碼。

以下是views.py中關于使用者登入子產品,具體登入請求會送出到這裡:

中間件middleware.py具體代碼(具體位置放在app應用下):

settings.py修改middleware_classes:

* 這樣就能實作傳回網站錯誤資訊啦:

關于django中間件使用的踩坑經曆背景起因詳細設計遇到的問題總結
做到這裡想必是做完了,但是我更想談談我在這過程遇到兩個問題,在這兩個問題裡可能花費的時間更多。
  由于将debug模式設定false之後,重新啟動項目後,發現所有的靜态檔案都無法通路。
關于django中間件使用的踩坑經曆背景起因詳細設計遇到的問題總結
  查了一下官方文檔,官方文檔給出的解釋就是,在開發過程中,django會提供django.contrib.staticfiles幫助管理靜态檔案,而開啟這一功能,除了需要包含在install_apps之外,還需要将dubug模式改為true。   是以略微分析,大概就知道我們靜态檔案404通路不到的原因了,簡單來說就是django提供給我們的靜态檔案路由功能不能用了,導緻404錯誤。 當然官方貼心的給出了額外的建議: 使用serve()視圖提供靜态資源通路服務。 通過nginx、apache等代理靜态資源。 而對于在生産環境下,官方更推薦的是第二種方法,原因無非就兩個: django提供的serve()視圖僅用于開發輔助使用,不适合生産使用。 nginx處理靜态資源有着更強的性能優勢。
 這裡我們就先通過上面提到第一種方法來解決“靜态資源404的問題”。  而關于django和nginx部署django項目的,之前在一篇文章裡介紹過,大家有興趣可以去看看:https://blog.51cto.com/mbb97/2151933

解決這一問題其實很簡單,直接修改urls.py,直接在urlpatterns清單下增加多一段代碼,比對靜态資源請求路徑,調用django内置靜态資源處理方法serve(),大功告成。

* 重新開機django項目,大功告成,第一個問題解決

關于django中間件使用的踩坑經曆背景起因詳細設計遇到的問題總結
我把這個中間件檔案複制到另外一個項目中,打算一勞永逸,沒想到竟然出錯了:
關于django中間件使用的踩坑經曆背景起因詳細設計遇到的問題總結
 首先我檢查的就是版本的問題,我看了一下剛剛中間件成功的那個項目是屬于django1.8.2版本,而如今報錯的項目沒想到是django2.0版本。  我查了官方文檔,以下是官方文檔的解釋,有興趣的可以了解以下:  https://docs.djangoproject.com/zh-hans/2.2/topics/http/middleware/  而參考官網給出的解決方法,就是通過django提供的django.utils.deprecation.middlewaremixin類,它能夠輕松相容新版的middleware和舊版的middleware_classes。

以下是示例代碼,修改中間件能夠輕松相容django新版本和舊版本:

重新開機項目,沒有報錯:

關于django中間件使用的踩坑經曆背景起因詳細設計遇到的問題總結

問題解決,管理者使用者能夠看到網站錯誤資訊:

關于django中間件使用的踩坑經曆背景起因詳細設計遇到的問題總結
 沒想到一個小小的中間件功能實作竟然途中遇到了這麼多問題,但是在遇到問題的過程中排查問題的方向都是大緻正确的,說起不足的地方還是對于django的整體架構知識不夠紮實。  由于django上很多東西都是等到需要用的時候,才會去查找資料,這也導緻很多問題不能第一時間反應解決。是以對于django新版本和舊版本之間的差別沒有及時的整理,以及類似中間件重要的知識點沒有及時歸納。  以後盡量抽時間整理一下django的架構知識,當然工作學習過程中踩到的坑能夠分享,也是對自己另外的一種學習提升。