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訊號,訂閱這個訊號的事件會清空並釋放任何使用中的資源。
如果您覺得本文對您有參考價值,歡迎幫博主點選文章下方的推薦,謝謝!