Flask 學習筆記:Flask應用的基本架構

1 知識儲備

在學習Flask應用之前,讓我們先了解一些術語。

1.1 Web服務器

  • Web服務器是一般指網站服務器,是指駐留於因特網上某種類型計算機的程序,可以向瀏覽器等Web客戶端提供文檔,也可以放置網站文件,讓全世界瀏覽;可以放置數據文件,讓全世界下載
  • 目前主流的Web服務器有:TomcatNginxIIS

1.2 Web應用程序

1.3 認識WSGI-Web服務器網關接口

  • WSGI,是Python語言定位的Web服務器與Web應用程序或框架之間的一種簡單而通用的接口
  • WSGI沒有官方實現,更像是一種協議,主要遵循這種協議,WSGI應用程序都可以在任何服務器上部署、運行,反之亦然
  • WSGI分爲兩個部分,一個是“服務器”或者“網關”,一個是“應用程序”或者“應用框架”。在處理WSGI請求時,服務器會爲應用程序提供環境信息以及一個回調函數;當應用程序完成處理請求後,通過回調函數將結果信息返回給服務器

2 Flask應用基本結構

2.1 Flask初始化

實例化Flask對象是編寫Flask應用程序的第一步。實例化的Flask即可實例化一個WSGI應用程序,並充當核心對象。該過程需要傳入應用程序的模塊或包的名稱。一旦該對象成功,它將成爲View FunctionURL RulesTemplate 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中動態部分默認是字符串類型,也可以顯示定義其他類型,例如:intfloatpath,其中,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_appg變量;請求上下文被推送之後,就可以在當前線程中使用requestsession變量。如果在沒有激活應用上下文或者請求上下文之前使用這些變量,將會導致錯誤。

  • request對象常用屬性和方法
屬性或方法 說明
form 一個字典,存儲請求提交的所有表單字段
args 一個字典,存儲通過URL查詢字符串傳遞的所有參數
values 一個字典,formargs的合集
cookies 一個字典,存儲請求的所有的cookie
headers 一個字典,存儲請求所有的HTTP首部
files 一個字典,存儲請求上傳的所有文件
get_data() 返回請求主體緩衝的數據
get_json() 返回一個字典,包含解析請求主體後得到的JSON
blueprint 處理請求的Flask藍本的名稱
endpoint 處理請求的Flask端點的名稱,Flask會將視圖函數的名稱用作路由端點的名稱
method HTTP請求方法,例如GETPOST
scheme URL方案,httphttps
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>'
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章