在應用 Django 的時候,咱們常常聽到一些術語:html
下面以 fastcgi 方式爲例,Django的版本是 "1.1" 。node
其實和其餘Web框架同樣,HTTP處理的流程大體相同(但和Tomcat等Java容器不相同),python
好比request->response.程序員
Django的配置都在 "Project/settings.py" 中定義,能夠是Django的配置,也能夠是自定義的配置,而且都經過 django.conf.settings 訪問,很是方便。正則表達式
最核心動做的是經過 django.core.management.commands.runfcgi 的 Command 來啓動,它運行 django.core.servers.fastcgi 中的 runfastcgi , runfastcgi 使用了 flup 的 WSGIServer 來啓動 fastcgi 。而 WSGIServer 中攜帶了 django.core.handlers.wsgi 的 WSGIHandler 類的一個實例,經過 WSGIHandler來處理由Web服務器(好比Apache,Lighttpd等)傳過來的請求,此時纔是真正進入Django的世界。數據庫
當有HTTP請求來時, WSGIHandler 就開始工做了,它從 BaseHandler 繼承而來。 WSGIHandler 爲每一個請求建立一個 WSGIRequest 實例,而 WSGIRequest 是從 http.HttpRequest 繼承而來。接下來就開始建立 Response 了.django
BaseHandler 的 get_response 方法就是根據 request 建立 response , 而具體生成 response 的動做就是執行 urls.py 中對應的view函數了,這也是 Django能夠處理「友好URL」的關鍵步驟,每一個這樣的函數都要返回一個 Response 實例。此時通常的作法是經過 loader 加載 template 並生成頁面內容,其中重要的就是經過 ORM 技術從數據庫中取出數據,並渲染到 Template 中,從而生成具體的頁面了數組
Django 返回 Response 給 flup , flup 就取出 Response 的內容返回給 Web 服務器,由後者返回給瀏覽器。瀏覽器
總之, Django 在 fastcgi 中主要作了兩件事:處理 Request 和建立 Response , 而它們對應的核心就是「urls分析」、「模板技術」和「ORM技術」,這些留在之後分析。附圖緩存
首先發生的是一些和 Django 有關(前期準備)的其餘事情,分別是:
這兩個類都繼承自 django.core.handlers.base.BaseHandler,它包含對任何類型的 request 來講都須要的公共代碼。
當上面其中一個處理器實例化後,緊接着發生了一系列的事情:
最後一條有點複雜,咱們仔細瞧瞧。
一 個 middleware 類能夠滲入處理過程的四個階段:request,view,response 和 exception。要作到這一點,只須要定義指定的、恰當的方法:process_request,process_view, process_response 和 process_exception。middleware 能夠定義其中任何一個或全部這些方法,這取決於你想要它提供什麼樣的功能。
當處理器內省 middleware 時,它查找上述名字的方法,並創建四個列表做爲處理器的實例變量:
如今處理器已經準備好真正開始處理了,所以它給調度程序發送一個信號 request_started(Django 內部的調度程序容許各類不一樣的組件聲明它們正在幹什麼,並能夠寫一些代碼監聽特定的事件。關於這一點目前尚未官方的文檔,但在 wiki上有一些註釋。)。接下來它實例化一個 django.http.HttpRequest 的子類。根據不一樣的處理器,多是 django.core.handlers.modpython.ModPythonRequest 的一個實例,也多是 django.core.handlers.wsgi.WSGIRequest 的一個實例。須要兩個不一樣的類是由於 mod_python 和 WSGI APIs 以不一樣的格式傳入 request 信息,這個信息須要解析爲 Django 可以處理的一個單獨的標準格式。
一旦一個 HttpRequest 或者相似的東西存在了,處理器就呼叫它本身的 get_response 方法,傳入這個 HttpRequest 做爲惟一的參數。這裏就是幾乎全部真正的活動發生的地方。
get_response 作的第一件事就是遍歷處理器的 _request_middleware 實例變量並呼叫其中的每個方法,傳入 HttpRequest 的實例做爲參數。這些方法能夠選擇短路剩下的處理並當即讓 get_response 返回,經過返回自身的一個值(若是它們這樣作,返回值必須是 django.http.HttpResponse 的一個實例,後面會討論到)。若是其中之一這樣作了,咱們會當即回到主處理器代碼,get_response 不會等着看其它 middleware 類想要作什麼,它直接返回,而後處理器進入 response 階段。
然而,更通常的狀況是,這裏應用的 middleware 方法簡單地作一些處理並決定是否增長,刪除或補充 request 的屬性。
假設沒有一個做用於 request 的 middleware 直接返回 response,處理器下一步會嘗試解析請求的 URL。它在配置文件中尋找一個叫作 ROOT_URLCONF 的配置,用這個配置加上根 URL /,做爲參數來建立 django.core.urlresolvers.RegexURLResolver 的一個實例,而後呼叫它的 resolve 方法來解析請求的 URL 路徑。
URL resolver 遵循一個至關簡單的模式。對於在 URL 配置文件中根據 ROOT_URLCONF 的配置產生的每個在 urlpatterns 列表中的條目,它會檢查請求的 URL 路徑是否與這個條目的正則表達式相匹配,若是是的話,有兩種選擇:
注意這一過程會在匹配到第一個指定了 view 的條目時中止,所以最好讓你的 URL 配置從複雜的正則過渡到簡單的正則,這樣能確保 resolver 不會首先匹配到簡單的那一個而返回錯誤的 view function。
若是沒有找到匹配的條目,resolver 會產生 django.core.urlresolvers.Resolver404 例外,它是 django.http.Http404 例外的子類。後面咱們會知道它是如何處理的。
一旦知道了所需的 view function 和相關的參數,處理器就會查看它的 _view_middleware 列表,並呼叫其中的方法,傳入 HttpRequst,view function,針對這個 view 的位置參數列表和關鍵字參數字典。
還有,middleware 有可能介入這一階段並強迫處理器當即返回。
若是處理過程這時候還在繼續的話,處理器會呼叫 view function。Django 中的 Views 不很嚴格由於它只須要知足幾個條件:
除了這些,你就能夠天馬行空了。儘管如此,通常來講,views 會使用 Django 的 database API 來建立,檢索,更新和刪除數據庫的某些東西,還會加載並渲染一個模板來呈現一些東西給最終用戶。
Django 的模板系統有兩個部分:一部分是給設計師使用的混入少許其它東西的 HTML,另外一部分是給程序員使用純 Python。
從一個 HTML 做者的角度,Django 的模板系統很是簡單,須要知道的僅有三個結構:
變量引用以一種很是簡單的方式工做。若是你只是要打印變量,只要 {{ foo }},模板系統就會輸出它。這裏惟一的複雜狀況是 {{ foo.bar }},這時模板系統按順序嘗試幾件事:
若是全部這些都失敗了,模板系統輸出配置 TEMPLATE_STRING_IF_INVALID 的值,默認是空字符串。
模板過濾就是簡單的 Python functions,它接受一個值和一個參數,返回一個新的值。好比,date 過濾用一個 Python datetime 對象做爲它的值,一個標準的 strftime 格式化字符串做爲它的參數,返回對 datetime 對象應用了格式化字符串以後的結果。
模板標籤用在事情有一點點複雜的地方,它是你瞭解 Django 的模板系統是如何真正工做的地方。
在內部,一個 Django 模板體現爲一個 「nodes」 集合,它們都是從基本的 django.template.Node 類繼承而來。Nodes 能夠作各類處理,但有一個共同點:每個 Node 必須有一個叫作 render 的方法,它接受的第二個參數(第一個參數,顯然是 Node 實例)是 django.template.Context 的一個實例,這是一個相似於字典的對象,包含全部模板能夠得到的變量。Node 的 render 方法必須返回一個字符串,但若是 Node 的工做不是輸出(好比,它是要經過增長,刪除或修改傳入的 Context 實例變量中的變量來修改模板上下文),能夠返回空字符串。
Django 包含許多 Node 的子類來提供有用的功能。好比,每一個內置的模板標籤都被一個 Node 的子類處理(好比,IfNode 實現了 if 標籤,ForNode 實現了 for 標籤,等等)。全部內置標籤能夠在 django.template.defaulttags 找到。實際上,上面介紹的全部模板結構都是某種形式的 Nodes,純文本也不例外。變量查找由 VariableNode 處理,出於天然,過濾也應用在 VariableNode 上,標籤是各類類型的 Nodes,純文本是一個 TextNode。
通常來講,一個 view 渲染一個模板要通過下面的步驟,依次是:
Template 的 render 方法的返回值是一個字符串,它由 Template 中全部 Nodes 的 render 方法返回的值鏈接而成,呼叫順序爲它們出如今 Template 中的順序。
一旦一個模板完成渲染,或者產生了其它某些合適的輸出,view 就會負責產生一個 django.http.HttpResponse 實例,它的構建器接受兩個可選的參數:
若是 view 函數,或者其中的什麼東西,發生了例外,那麼 get_response(我知道咱們已經花了些時間深刻 views 和 templates,可是一旦 view 返回或產生例外,咱們仍將重拾處理器中間的 get_response 方法)將遍歷它的 _exception_middleware 實例變量並呼叫那裏的每一個方法,傳入 HttpResponse 和這個 exception 做爲參數。若是順利,這些方法中的一個會實例化一個 HttpResponse 並返回它。
這時候有可能仍是沒有獲得一個 HttpResponse,這可能有幾個緣由:
這時候,get_response 會回到本身的例外處理機制中,它們有幾個層次:
此外,對於除了 django.http.Http404 或 Python 內置的 SystemExit 以外的任何例外,處理器會給調度者發送信號 got_request_exception,在返回以前,構建一個關於例外的描述,把它發送給列在 Django 配置文件的 ADMINS 配置中的每個人。
如今,不管 get_response 在哪個層次上發生錯誤,它都會返回一個 HttpResponse 實例,所以咱們回處處理器的主要部分。一旦它得到一個 HttpResponse 它作的第一件事就是遍歷它的 _response_middleware 實例變量並應用那裏的方法,傳入 HttpRequest 和 HttpResponse 做爲參數。
注意對於任何想改變點什麼的 middleware 來講,這是它們的最後機會。
是該結束的時候了。一旦 middleware 完成了最後環節,處理器將給調度者發送信號 request_finished,對與想在當前的 request 中執行的任何東西來講,這絕對是最後的呼叫。監聽這個信號的處理者會清空並釋聽任何使用中的資源。好比,Django 的 request_finished 監聽者會關閉全部數據庫鏈接。
這件事發生之後,處理器會構建一個合適的返回值送返給實例化它的任何東西(如今,是一個恰當的 mod_python response 或者一個 WSGI 兼容的 response,這取決於處理器)並返回。
結束了,從開始到結束,這就是 Django 如何處理一個 request。