1 知識儲備
在學習Flask
應用之前,讓我們先了解一些術語。
1.1 Web服務器
- Web服務器是一般指網站服務器,是指駐留於因特網上某種類型計算機的程序,可以向瀏覽器等Web客戶端提供文檔,也可以放置網站文件,讓全世界瀏覽;可以放置數據文件,讓全世界下載
- 目前主流的
Web服務器
有:Tomcat
、Nginx
和IIS
1.2 Web應用程序
- Web應用程序一般是指可以通過
Web
訪問的應用程序
1.3 認識WSGI-Web服務器網關接口
WSGI
,是Python
語言定位的Web
服務器與Web
應用程序或框架之間的一種簡單而通用的接口WSGI
沒有官方實現,更像是一種協議,主要遵循這種協議,WSGI
應用程序都可以在任何服務器上部署、運行,反之亦然WSGI
分爲兩個部分,一個是“服務器”或者“網關”,一個是“應用程序”或者“應用框架”。在處理WSGI
請求時,服務器會爲應用程序提供環境信息以及一個回調函數;當應用程序完成處理請求後,通過回調函數將結果信息返回給服務器
2 Flask應用基本結構
2.1 Flask初始化
實例化Flask
對象是編寫Flask
應用程序的第一步。實例化的Flask
即可實例化一個WSGI
應用程序,並充當核心對象。該過程需要傳入應用程序的模塊或包的名稱。一旦該對象成功,它將成爲View Function
、URL Rules
和Template Configuration
等的核心註冊對象。
Flask
初始化很簡單,只需傳入一個參數,即應用程序主模塊或包的名稱,一般傳入__name__
即可,示例代碼如:
from flask import Flask
app = Flask(__name__)
2.1.1 理解Flask傳入的第一個參數
Flask
應用程序可根據這個參數,從當前包或者包含當前模塊(.py
文件)的文件夾內查詢資源;另外,Flask
的擴展也可根據這個參數優化調試信息等等。
官網建議,如果使用一個單獨的模塊(即:一個獨立的.py
文件),傳入__name__
即可;如果使用一個包(含__init__.py
文件的文件夾),通常建議此處填入包的名稱;如果這種情況仍然傳入__name__
,程序也可以正常運行,不過在測試環境中,某個擴展可能會出現意想不到的問題。
2.2 路由
2.2.1 什麼是路由
客戶端將請求發送給Web
服務器,然後Web
服務器將請求轉發給Flask
應用示例。而,應用示例接收到URL
請求後需要知道它該運行哪些代碼,所需要保存URL
和函數的映射對應關係,而存儲這些關係的就是路由。
2.2.2 定義路由
Flask
中定義路由有兩種方式:
- 簡便的方式,使用應用實例提供的
app.route
裝飾器,如下:
@app.rout("\")
def index():
return '<h1>Hello World</h1>'
- 傳統的方式,使用
app.add_url_rule
方法,該方法接收3個參數:URL
、斷點(endpoint)和視圖函數,如下:
def index():
return '<h1>Hello World</h1>'
app.add_url_rule('/', 'index', index)
處理類似index
這種入站請求的函數統稱爲視圖函數
2.2.3 定義動態路由
Flask
支持動態路由,只需在URL
中使用對應的句法即可,例如/user/<name>
,其中<>
中的內容就是動態的,其他內容是該URL
中靜態部分,Flask
會將動態部分作爲參數傳入給視圖函數。
Flask
中動態部分默認是字符串類型,也可以顯示定義其他類型,例如:int
、float
和path
,其中,path
類型是一種特殊的字符串,它可以包含正斜線。
2.3 Web開發服務器
Flask
中自帶Web開發服務器,可通過flask run
命令啓動,需提前配置FLASK_APP
環境變量,給該命令指定從哪個Python
腳本中尋找應用示例。
以運行hello.py
這個文件爲例
# Linux和MacOS
export FLASK_APP=hello.py
flask run
# Windows
set FLASK_APP=hello.py
flask run
Web
開發服務器啓動後,便開始輪訓,處理請求,直到該服務器停止。
除了使用flask run
的方式,也可以使用編程的方式啓動:調用app.run
方法。在之前舊版本中,若想啓動應用,需要運行應用的主腳本,該主腳本需要在其尾部增加如下內容:
if __name__ == '__main__':
app.run()
現有版本中,常使用flask run
命令啓動,不過在單元測試中,也可使用編程方式啓動應用。
2.4 調試模式
Flask
調試模式默認會加載兩個便利的工具:重載器和調試器。
- 重載器
啓用重載器後,Flask
會監聽項目中所有的源代碼文件,發現變動後自動重啓服務器。
- 調試器
調試器是基於Web
工具,當應用跑出未處理的異常時,它會出現在瀏覽器中。
啓用調試模式方式如下:
- 當使用
flask run
命令
在使用flask run
之前設定FLASK_DEBUG=1
環境變量
- 當使用
app.run()
方式
當使用這種方式時,需傳遞參數debug=True
,即app.run(debug=True)
2.5 請求-響應循環
2.5.1 應用和請求上下文
Flask
從客戶端接收到請求後,會使用臨時上下文將某些對象變爲全局訪問,以便讓視圖函數能夠訪問,從而處理這些請求,其調用方式如下:
from flask import request
需要提醒的是,request
只是被當做全局變量訪問,但事實上肯定不會是全局變量。因爲,在多線程Web
服務器中,多個線程同時處理不同客戶端發送的請求時,每個線程接收到的request
對象必然是不同的。
在Flask
中,上下文可分爲應用上下文和請求上下文,如下:
變量名 | 上下文 | 說明 |
---|---|---|
current_app |
應用上下文 | 當前應用的應用實例 |
g |
應用上下文 | 處理請求時用作臨時存儲的對象,每次請求都會重設這個變量 |
request |
請求上下文 | 請求對象,封裝了客戶端發出的HTTP 請求中內容 |
session |
請求上下文 | 用戶會話,值爲一個字典,存儲請求之間需要“記住”的值 |
Flask
在分派請求之前激活(或者推送)應用和請求上下文,請求處理完成之後再將其刪除。也就是,應用上下文被推送之後,就可以在當前線程中使用current_app
和g
變量;請求上下文被推送之後,就可以在當前線程中使用request
和session
變量。如果在沒有激活應用上下文或者請求上下文之前使用這些變量,將會導致錯誤。
request
對象常用屬性和方法
屬性或方法 | 說明 |
---|---|
form |
一個字典,存儲請求提交的所有表單字段 |
args |
一個字典,存儲通過URL查詢字符串傳遞的所有參數 |
values |
一個字典,form 和args 的合集 |
cookies |
一個字典,存儲請求的所有的cookie |
headers |
一個字典,存儲請求所有的HTTP 首部 |
files |
一個字典,存儲請求上傳的所有文件 |
get_data() |
返回請求主體緩衝的數據 |
get_json() |
返回一個字典,包含解析請求主體後得到的JSON |
blueprint |
處理請求的Flask 藍本的名稱 |
endpoint |
處理請求的Flask 端點的名稱,Flask 會將視圖函數的名稱用作路由端點的名稱 |
method |
HTTP 請求方法,例如GET 和POST |
scheme |
URL 方案,http 或https |
is_secure() |
通過安全的鏈接(HTTPS )發送請求時返回True |
host |
請求定義的主機名,如果客戶端定義了端口號,還包括端口號 |
path |
URL 路徑部分 |
query_string |
URL 的查詢字符串部分,返回原始的二進制值 |
full_path |
URL 路徑和查詢字符串部分 |
url |
客戶端請求的完整的URL |
base_url |
同url ,但沒有查詢字符串部分 |
remote_addr |
客戶端的IP 地址 |
environ |
請求的原始WSGI 環境字典 |
2.5.2 請求分派
Flask
爲了完成將客戶端發來的請求與視圖函數相對應,會從應用的URL映射中查找請求的URL。URL映射是URL和視圖函數之間的對應關係。
若想查看Flask
中定義的URL映射會是什麼樣子,可調用應用實例的url_map
屬性,如下:
from hello.py import app
app.url_map
2.5.3 請求鉤子
有時我們需要在請求之前和請求之後執行相關代碼,例如,在請求開始時,可能需要創建數據庫連接或者驗證發起請求的用戶身份。
Flask
提供註冊通用函數的功能,註冊的函數可在請求被分派到視圖函數之前或之後調用,通用註冊函數有:
before_request
註冊一個函數,在每次請求之前運行
before_first_request
註冊一個函數,只在處理第一個請求之前運行。可以通過這個鉤子添加服務器初始化任務
after_request
註冊一個函數,如果沒有未處理的異常拋出,在每次請求之後運行
teardown_request
註冊一個函數,即使有未處理的異常拋出,也在每次請求之後運行
在請求鉤子函數和視圖函數之間共享數據一般會用應用上下文全局變量g
。
2.5.4 響應
Flask
調用視圖函數後,會將其返回值作爲響應內容。一般情況下,響應及時一個簡單的字符串,作爲HTML
頁面返回給瀏覽器端。
Flask
響應可包括3個參數,第一個參數是上面提到的響應內容,第二個參數是狀態碼,默認爲200,第三個參數是HTTP
響應頭部組成的字符串。
Flask
視圖函數還可以返回一個響應對象make_response()
,該函數可接受1、2或3個參數(與視圖函數的返回值相對應),即make_response
會返回一個等效的響應對象。
響應對象常用屬性和方法如下:
屬性或方法 | 描述 |
---|---|
status_code |
HTTP 數字狀態碼 |
headers |
一個類似字典的對象,包含隨響應發送的所有首部 |
set_cookie() |
爲響應添加一個cookie |
delete_cookie() |
刪除一個cookie |
content_length |
響應主體的長度 |
content_type |
響應主題的媒體類型 |
set_data() |
使用字符串或字節值設定響應 |
get_data() |
獲取響應主體 |
一些特殊的響應
- 重定向響應
重定向響應沒有頁面文檔,只會告訴瀏覽器一個URL
,用來加載新頁面。該響應對應的狀態爲302,在Location
首部提供目標URL
。
Flask
中提供了redirect()
輔助函數,用來生成這種響應,如下:
from flask import redirect
@app.rout("/")
def index():
return redirect("http://www.baidu.com")
- 錯誤響應
Flask
中可用abort
函數生成該響應,如下:
from flask import abort
@app.rout("/usr/<id>")
def get_user(id):
user = load_user(id)
if not user:
abort(404)
return '<h1>hello</h1>'