之前用 Django 做過一個小的站點,感覺Django太過笨重,於是就準備換一個比較輕量級的 Web 框架來玩玩。 Web.py 作者已經掛掉,專案好久沒有更新,所以不準備用它。而 Flask 也是一個成熟的輕量級 Web 框架,在 github 上有眾多的 Star 和 Fork,文件和擴充功能也很豐富,值得學習。
學習框架最好的方式就是用框架做一個項目,在實戰中理解掌握框架。這裡我用 Flask 框架,使用 Mysql 資料庫做了一個 論壇系統 。麻雀雖小,五臟俱全,論壇效果圖如下:
論壇系統截圖
#下面是論壇的基本功能:
##完整的用戶模組(註冊、登錄,更改、找回密碼、資訊修改、站內訊息通知); 豐富的論壇模組(創建、回复話題,站內搜索,markdown支持,@user 提醒); 強大的後台管理,支持屏蔽使用者、主題、評論,支持各種條件搜尋主題、評論;本部落格將會用一系列文章,記錄論壇系統搭建的過程,希望對剛入門Web開發的同學有所幫助。 我們常聽說Django, Flask 這些python 語言的Web 框架,那麼框架到底是什麼,Web框架和Web伺服器(Nginx, Apache等)有什麼區別?離開框架還能用Python 搭建Web站點?要解決這些疑問,我們有必要來理解下Web 伺服器的工作原理,以及Web 框架的本質。Web 伺服器
當我們在瀏覽器輸入URL後,瀏覽器會先請求 DNS伺服器,取得請求網站的 IP 位址 。然後發送一個HTTP Request(請求)給擁有該 IP 的主機,接著就會接收到伺服器給我們的 HTTP Response(回應),瀏覽器經過渲染後,以一種較好的效果呈現給我們。這個過程中,正是Web伺服器在幕後默默做出貢獻。 簡單來說,Web伺服器是在運行在實體伺服器上的程序,它永久地等待客戶端(主要是瀏覽器,例如Chrome,Firefox等)發送請求。當收到請求之後,它會產生相應的回應並將其返回至客戶端。 Web伺服器透過HTTP協定與客戶端通信,因此也稱為HTTP伺服器。Web 伺服器
Web伺服器的工作原理並不複雜,一般可分成以下4個步驟:建立連線、請求過程、應答過程以及關閉連線。 建立連線:客戶機透過TCP/IP協定建立到伺服器的TCP連線。 請求流程:客戶端向伺服器傳送HTTP協定請求包,請求伺服器裡的資源文件。 應答過程:伺服器向客戶機發送HTTP協定應答包,如果請求的資源包含有動態語言的內容,那麼伺服器會呼叫動態語言的解釋引擎負責處理“動態內容”,並將處理得到的資料傳回給客戶端。由客戶端解釋HTML文檔,在客戶端螢幕上渲染圖形結果。 關閉連線:客戶機與伺服器斷開。 下面我們實作一個簡單的 Web 伺服器。執行範例程式後,會監聽本機連接埠 8000,在瀏覽器造訪 http://www.php.cn/:8000 就能看到回應內容。而我們的程式也能夠列印出客戶端寄來的請求內容,如下圖:簡單Web伺服器
這裡Request 和Response 都需要遵守HTTP 協議,關於HTTP 協議的詳細內容,可以讀讀《HTTP 權威指南》,或看我整理的HTTP 部分內容。 雖然說web伺服器的主要工作是根據request返回response,但是實際中的Web 伺服器遠遠比上面範例的複雜的多,因為要考慮的因素實在是太多了,例如:快取機制:講一些經常被存取的頁面快取起來,提高回應速度; 安全性:防止駭客的各種攻擊,例如SYN Flood 攻擊; 並發處理:如何回應不同客戶端同時發起的請求; 日誌:記錄訪問日至,方便做一些分析。 目前在UNIX和LINUX平台下使用最廣泛的免費 Web 伺服器有Apache和 Nginx 。Web 應用程式
Web 伺服器接受 Http Request,返回 Response,很多時候 Response 並不是靜態文件,因此需要有一個應用程式根據 Request 產生相應的 Response。這裡的應用程式主要用來處理相關業務邏輯,讀取或更新資料庫,根據不同 Request 傳回對應的 Response。注意這裡並不是 Web 伺服器本身來做這件事,它只負責 Http 協定層面和一些諸如並發處理,安全,日誌等相關的事情。
應用程式可以用各種語言編寫(Java, PHP, Python, Ruby等),這個應用程式會從Web伺服器接收客戶端的請求,處理完成後,再回傳回應網路伺服器,最後由Web伺服器傳回給客戶端。整個架構如下:
Web應用程式
以Python 為例,使用Python開發Web,最原始且直接的辦法是使用CGI標準,在1998年這種方式很流行。首先確保Web 伺服器支援CGI及已經配置了CGI的處理程序,然後設定好CGI目錄,在目錄裡面添加相應的python 文件,每一個python 文件處理相應輸入,生成一個html 文件即可,如下例:
# !/usr/bin/python # -*- coding: UTF-8 -*- print "Content-type:text/html" print # 空行,告诉服务器结束头部 print '<html>' print '<head>' print '<meta charset="utf-8">' print '</head>' print '<body>' print '<h2>Hello Word! 我是一个CGI程序</h2>' print '</body>' print '</html>'
這樣在瀏覽器存取該檔案就可以得到一個簡單的Hello World 網頁內容。直接透過 CGI 寫入 Web 應用程式看起來很簡單,每個檔案處理輸入,產生html。但是在實際開發中,可能會遇到許多不方便的地方。例如:
每個獨立的CGI腳本可能會重複寫資料庫連接,關閉的程式碼; 後端開發者會看到一堆Content-Type 等和自己無關的html 頁面元素; Web框架
早期開發網站確做了許多重複性勞動,後來為了減少重複,避免寫出龐雜,混亂的程式碼,人們將Web 開發的關鍵性過程提取出來,開發出了各種Web 框架。有了框架,就可以專注於編寫清晰、易於維護的程式碼,無需關心資料庫連接之類的重複性工作。
其中一個比較經典的Web框架採用了MVC 架構,如下圖所示:
MVC 架構
使用者輸入URL,客戶端發送請求,控制器(Controller)首先會拿到請求,然後用模型(Models)從資料庫取出所有需要的數據,進行必要的處理,將處理後的結果傳送給視圖(View),視圖利用取得到的數據,進行渲染產生Html Response回傳給客戶端。
以 python web 框架 flask 為例,框架本身並不限定我們用哪種架構來組織我們的應用,不過 flask 可以很好地支援以 MVC 方式組織應用。
控制器:flask 可以用裝飾器來新增路由項,如下:
@app.route('/') def main_page(): pass
模型:主要用來取出所需的數據,如下面函數中操作:
@app.route('/') def main_page(): """Searches the database for entries, then displays them.""" db = get_db() cur = db.execute('select * from entries order by id desc') entries = cur.fetchall() return render_template('index.html', entries=entries)
視圖:flask 利用jinja2 來渲染頁面,下面的模版檔案指定了頁面的樣式:
#{% for entry in entries %} <li> <h2>{{ entry.title }}</h2> <p>{{ entry.text|safe }}</p> </li> {% else %} <li><em>No entries yet. Add some!</em></li> {% endfor %}
我們知道Python有著許多的Web 框架,而同時又有著許多的Web 伺服器(Apache, Nginx, Gunicorn等),框架和Web伺服器之間需要進行通信,如果在設計時它們之間不可以相互匹配的,那麼選擇了一個框架就會限制對Web 伺服器的選擇,這顯然是不合理的。
那麼,怎樣確保可以在不修改Web伺服器程式碼或網路框架程式碼的前提下,使用自己選擇的伺服器,並且匹配多個不同的網路框架呢?答案是接口,設計一套雙方都遵守的介面就可以了。對python來說,就是WSGI(Web Server Gateway Interface,Web伺服器網關介面)。其他程式語言也擁有類似的介面:例如Java的Servlet API和Ruby的Rack。
Python WSGI的出現,讓開發者可以將 Web 框架與 Web 伺服器的選擇分隔開來,不再互相限制。現在,你可以真正地將不同的 Web 伺服器與Web框架進行混搭,選擇滿足自己需求的組合。例如,可以使用 Gunicorn 或Nginx/uWSGI來運行Django、Flask或web.py應用。
更多Python 建立Web站點之Web伺服器與Web框架相關文章請關注PHP中文網!