Flask 學習筆記(一)
一、Web 服務器與 Web 框架
首先明確一下,要運行一個動態網頁,我們需要
- 一個 Web 服務器來監聽並響應請求
- 一個 Web 應用來處理請求,生成響應
其中 Web 服務器通常都是別人已經實現好了的,它通過定義好的接口與我們編寫的 Web 應用通信。WSGI 就是一個統一的 Web 服務器接口標準,如果我們按照 WSGI 編寫 Web 應用,那麽它就能在任何符合該標準的服務器上運行,例如 Gunicorn 和 uWSGI + nginx。(對比一下 Java 的 Servlet,按照 Servlet 規範編寫的應用,都能運行在任何 Servlet 容器上,例如 Tomcat 和 Jetty,Servlet 容器就相當於 WSGI 服務器)
可是 WSGI 仍然比較底層,直接照著它寫太麻煩,於是就有了 Web 框架,Python 知名的就是 Flask 和 Django,Java 對應的是 Spring MVC. 但是 Flask 和 Django 都有內置服務器用於測試,而 Spring MVC 沒有,倒是 Spring Boot 可以使用內嵌的 tomcat 容器。
二、Flask
Flask 是一個微框架,“微”是指它的核心非常小,任何可選的功能都不包括在內。但是 Flask 社區提供了豐富的拓展插件,你可以通過選擇需要的插件來實現你想要的功能。
中間略過 n 萬字。。。
三、上下文 Context
1. 請求上下文 Request Context
Java 的 Spring MVC 將請求作為方法參數傳入,而且要求參數必須映射到某個類型或者某個 model 上。
Flask 的處理方式與之不同,它提供了一個全局代理對象——request,只要是在請求從開始到結束的過程中,都可以直接通過這個 request 訪問 HTTP 請求的各種參數。
請求上下文在請求開始時被壓入棧,這時 request 對象才可用,在請求結束後會立即被 pop 出來。
2. 應用上下文 Application Context
一個 app,就是一個 Flask 實例,通過 app = Flask(__name__)
創建。
在請求到來時,除了請求上下文被入棧,還有應用上下文也會被入棧。
也就是說在請求過程中,應用上下文是可用的,這時可以通過 current_app 訪問當前 app 的相關數據。
疑問
- 在 flask 初始化時,我們不是已經通過
app = Flask(__name__)
創建了一個 app 實例了麽?直接用它不行麽?
這是因為所有的 flask 模塊都需要在 app 對象中註冊,在其它模塊導入 app 會出現循環導入的問題。
3. g 對象
g 對象,名稱來源於 global
,保存在應用上下文中,指應用上下文中的全局變量。
應用上下文只是對當前 app 的一個代理,它的生命周期和請求上下文相同,因此 g 顯然也只存在於當前請求過程中,不能用於跨請求傳遞數據。
4. session 對象
session 位於 請求上下文中,但是它的內容會被保存到 cookie 中,發送到客戶端。每次收到請求時又會從 cookie 中加載它。因此它可用於跨請求傳輸數據。
但是 session 不是安全的數據保存方式,只適合存放非敏感數據。
四、插件
- python-dotenv:配置文件
- flask_wtform:表單
- flask-login:登錄與權限驗證
- flask-sqlalchemy + flask-migrate:數據庫
- flask-restplus:restful api
- flask-SocketIO:websocket
四、使用 blueprint(藍圖)
入門級 flask app 都是單文件應用,當復雜度上升,我們可以把單文件應用分成多個文件,比如:views.py、models.py、forms.py、errors.py。
但是如果項目繼續增大,各個文件也會漸漸變得難以維護。views.py 中各種功能的視圖函數混在一起,models.py 和 forms.py 也是。顯然我們可以按功能,繼續分割這幾個代碼文件。
blueprint 就是用於應對大型項目開發的功能,使用它可以對上述的文件按功能做進一步的拆分。
藍圖使用起來就像應用當中的子應用一樣,可以有自己的模板,靜態目錄,有自己的視圖函數和URL規則,藍圖之間互相不影響。但是它們又屬於應用中,可以共享應用的配置。
實際上 BluePrint 類的使用也幾乎和 Flask 一模一樣。差別只是 BluePrint 最後還需要在 Flask 實例中註冊:app.register_blueprint(<blue_print_obj>)
.
註意事項
- url_for 的第一個參數 endpoint,是 view function 的名稱,不是 route 路徑!
- 使用 blueprint 時,endpoint 為
藍圖名稱.視圖函數名稱
- 使用 blueprint 時,endpoint 為
- 讀取資源文件:資源文件可以放在
data
文件夾下,使用flask.open_resources("data/<file_name>", mode="rb")
讀取資源文件。- 不放在
static
下的原因是,該目錄內的文件是可以直接通過 URI/static/<file_path>
訪問的,是公開的。我們一般不希望用戶直接訪問這種資源文件。
- 不放在
鏈接
- flask
- the-flask-mega-tutorial
- flask的上下文疑問 current_app, g, session, request?
- Flask的g對象,範圍是什麽?
- Modular Applications with Blueprints
Flask 學習筆記(一)