As we all know,所有的Web應用,其本質上其實就是一個socket服務端,而用戶的瀏覽器就是一個socket客戶端。
#!/usr/bin/env python #coding:utf-8 import socket def handle_request(client): buf = client.recv(1024) client.send("HTTP/1.1 200 OK\r\n\r\n") client.send("Hello, Seven") def main(): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(('localhost',8000)) sock.listen(5) while True: connection, address = sock.accept() handle_request(connection) connection.close() if __name__ == '__main__': main()
上述代碼使用socket實現了其本質,對於所有的python web程序來說,一般會分為兩部分:服務器程序和應用程序。服務器程序負責對socket服務器進行封裝,並在請求到來時,對請求的數據進行整理。應用程序則負責具體的邏輯處理。為了方便應用程序的開發,避免大家重復的造輪子,因此有人發明了相關的工具——Web框架,for example:Django、Flask、web.py and so on。不同的框架可能采用不同的目錄結構,但是無論如何,開發出的應用程序都要和服務器程序配合,才能為用戶提供服務。以前,如何選擇合適的Web應用程序框架成為困擾Python初學者的一個問題,這是因為,一般而言,Web應用框架的選擇將限制可用的Web服務器的選擇,反之亦然。那時的Python應用程序通常是為CGI,FastCGI,mod_python中的一個而設計,甚至是為特定Web服務器的自定義的API接口而設計的。
PythonWeb服務器網關接口(Python Web Server Gateway Interface,縮寫為WSGI)是Python應用程序或框架和Web服務器之間的一種接口,已經被廣泛接受, 它已基本達成它的可移植性方面的目標。
概述:
Django的請求到響應的流程,簡單的來說就是利用wsgi,當用戶發來一個request進行response,響應前發送request_started信號,經過中間件的process_request,響應完成后會調用中間件的process_response。
1.瀏覽器端用戶用url發來了一個請求
當django程序啟動時,會根據settings中:
源碼截圖:
(注:這里是project名.wsgi.application,博主創建的project名為s3。)
執行applicaion對應的函數:
源碼截圖:
接下來我們來看get_wsgi_application函數:
源碼截圖:
從上述源碼可看出django每次請求響應都會返回一個WSGIHandler類的實例。
WSGIHandler類源碼截圖:
這里,我們需要關注的是:
load_middleware只有第一次請求會調用,即中間件的加載只會在第一次請求時執行。
WSGIhandler類中發送了request_started信號。
下來我們首先關注一下他的父類base.BaseHandler類:
base.BaseHandler類源碼截圖:
中間件的完整執行流程圖:
備注:由上圖可看出:
- 當請求到來時,會首先經過中間件的Process_Request,如果Process_Request有return即當前url沒有通過中間件,則程序直接跳轉到最后一個Process_Response,然后逆序執行所有的Process_Response。
- 然后程序會進入url,這時程序會檢測用戶有沒有設置process_view,如果有,則接下來先執行process_view,如果process_view有return,則程序直接跳轉到最后一個Process_Response,然后逆序執行所有的Process_Response。
- 如果上一步沒有process_view,程序會執行views文件中的函數
- 執行完上一步,程序會檢測有沒有異常出現,如果有,則先執行中間件類對應的process_exception
- 最后,程序會逆序執行所有的Process_Response。
備注:request_middleware、view_middleware 是順序執行,template_response_middleware、response_middleware、exception_middleware 是逆序執行。
url:
首先程序會根據配置文件中:
源碼截圖:
(同樣這是是project名.urls)
找到urls.py文件
url匹配源碼:
這里直接使用當前url是否屬於LocaleRegexURLResolver這個類。
LocaleRegexURLResolver類:
預編譯:
正則匹配:
我們需要關注的是LocaleRegexURLResolver類的resolve方法:
注:self.url_patterns是所有的正則url,這里對正則url進行循環;new_path是用戶輸入的url,這里pattern.resolve是執行RegexURLPattern類的resolve方法:
由上述源碼可看出RegexURLPattern類的resolve方法即通過regex.search進行具體的匹配操作,其中regex封裝了re模塊。
我們定義的url:
示例代碼:
from django.conf.urls import url from django.contrib import admin from APP01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^articles/(?P<year>[0-9]{4})/$', views.special_case_2003), url(r'^articles/([0-9]{4})/$', views.year_archive), url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive), url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail), ]
源碼url截圖:
從上述源碼中可看出url方法接收正則表達式和view兩個參數,最終返回一個RegexURLPattern對象,RegexURLPattern類對正則表達式和view做進一步處理
由上述源碼可看出,在完成正則匹配后,view會被作為回調函數運行。由此解釋了url是如何與views函數進行綁定的。
接下來,程序調用views函數,並對模板進行渲染,並返回到view,程序如果沒有異常,執行中間件的Process_Response(詳見上文中間件的執行流程),最終程序發送一個信號 request_finished信號,訂閱這個信號的事件會清空並釋放任何使用中的資源。
如果您覺得本文對您有參考價值,歡迎幫博主點擊文章下方的推薦,謝謝!