配套視頻教程
- 初始化
所有的Flask程序都必須創建一個程序實例, 這個程序實例就是Flask類的對象。客戶端把請求發送給Web服務器, 服務器再把請求發送給Flask程序實例, 然后由程序實例處理請求。
創建程序實例:
from flask import Flask
app = Flask(__name__)
此處的__name__
是一個全局變量, 它的值是代碼所處的模塊或包的名字, Flask用這個參數決定程序的根目錄, 以便稍后能找到相對於程序根目錄的資源文件位置。
2.路由和視圖函數
客戶端把請求發送給Web服務器, 服務器再把請求發送給Flask程序實例, 然后由Flask程序實例處理請求。
程序實例如何處理請求, 答案是程序實例通過路由來處理請求——路由就是URL和處理請求的函數的映射——處理請求的函數就叫做視圖函數。
Flask定義路由最簡便的方式, 是使用程序實例提供的app.route修飾器:
@app.route('/'):
def index():
return '<h1>Hello world!<h1>'
前例把index()函數注冊為程序根地址的處理程序。 ( 如果部署程序的服務器域名為www.example.com, 在瀏覽器中訪問http://www.example.com后, 會觸發服務器執行index()函數。 )
這個函數的返回值稱為響應, 是客戶端接收到的內容。
地址中包含可變部分的路由:
@app.route('/user/<name>')
def user(name):
return '<h1>Hello, %s!</h1>' %name
尖括號中的內容就是動態部分,任何能匹配靜態部分的URL都會映射到這個視圖函數, 調用視圖函數時, Flask會將動態部分作為參數傳入函數。
注意:路由中的動態部分默認類型是字符串, 不過也可以使用別的類型如:/user/<int: id>只會匹配動態片段id為整數的url。
3.啟動服務器
Flask 應用自帶 Web 開發服務器,通過 flask run 命令啟動。這個命令在 FLASK_APP 環境變量指定的 Python 腳本中尋找應用實例。
Linux 和 macOS 用戶執行下述命令啟動 Web 服務器:
(venv) $ export FLASK_APP=app.py
(venv) $ flask run
* Serving Flask app "hello"
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
微軟 Windows 用戶執行的命令和剛才一樣,只不過設定 FLASK_APP 環境變量的方式不同:
(venv) $ set FLASK_APP=app.py
(venv) $ flask run
* Serving Flask app "hello"
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
服務器啟動后便開始輪詢,處理請求。直到按 Ctrl+C 鍵停止服務器,輪詢才會停止。
服務器運行時,在 Web 瀏覽器的地址欄中輸入 http://localhost:5000/。你看到的頁面如圖 2-1 所示。
Flask Web 開發服務器也可以通過編程的方式啟動:調用 app.run() 方法。
if __name__ == '__main__':
app.run(debug=True) #debug參數為True, 表示啟用調試模式。
命令行選項
flask 命令支持一些選項。執行 flask --help,或者執行 flask 而不提供任何參數,可以查看哪些選項可用:
(venv) $ flask --help
Usage: flask [OPTIONS] COMMAND [ARGS]...
This shell command acts as general utility script for Flask applications.
It loads the application configured (through the FLASK_APP environment
variable) and then provides commands either provided by the application or
Flask itself.
The most useful commands are the "run" and "shell" command.
Example usage:
$ export FLASK_APP=hello.py
$ export FLASK_DEBUG=1
$ flask run
Options:
--version Show the flask version
--help Show this message and exit.
Commands:
run Runs a development server.
shell Runs a shell in the app context.
flask shell 命令在應用的上下文中打開一個 Python shell 會話。在這個會話中可以運行維護任務或測試,也可以調試問題。幾章之后將舉例說明這個命令的用途。
flask run 命令我們已經用過,從名稱可以看出,它的作用是在 Web 開發服務器中運行應用。這個命令有多個參數:
(venv) $ flask run --help
Usage: flask run [OPTIONS]
Runs a local development server for the Flask application.
This local server is recommended for development purposes only but it can
also be used for simple intranet deployments. By default it will not
support any sort of concurrency at all to simplify debugging. This can be
changed with the --with-threads option which will enable basic
multithreading.
The reloader and debugger are by default enabled if the debug flag of
Flask is enabled and disabled otherwise.
Options:
-h, --host TEXT The interface to bind to.
-p, --port INTEGER The port to bind to.
--reload / --no-reload Enable or disable the reloader. By default
the reloader is active if debug is enabled.
--debugger / --no-debugger Enable or disable the debugger. By default
the debugger is active if debug is enabled.
--eager-loading / --lazy-loader
Enable or disable eager loading. By default
eager loading is enabled if the reloader is
disabled.
--with-threads / --without-threads
Enable or disable multithreading.
--help Show this message and exit.
--host 參數特別有用,它告訴 Web 服務器在哪個網絡接口上監聽客戶端發來的連接。默認情況下,Flask 的 Web 開發服務器監聽 localhost 上的連接,因此服務器只接受運行服務器的計算機發送的連接。下述命令讓 Web 服務器監聽公共網絡接口上的連接,因此同一網絡中的其他計算機發送的連接也能接收到:
(venv) $ flask run --host 0.0.0.0
* Serving Flask app "hello"
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
現在,網絡中的任何計算機都能通過 http://a.b.c.d:5000 訪問 Web 服務器。其中,a.b.c.d 是運行服務器的計算機的 IP 地址。
請求–響應循環
應用和請求上下文
Flask 從客戶端收到請求時,要讓視圖函數能訪問一些對象,這樣才能處理請求。請求對象就是一個很好的例子,它封裝了客戶端發送的 HTTP 請求。
為了避免大量可有可無的參數把視圖函數弄得一團糟,Flask 使用上下文臨時把某些對象變為全局可訪問。有了上下文,便可以像下面這樣編寫視圖函數:
from flask import request
@app.route('/')
def index():
user_agent = request.headers.get('User-Agent')
return '<p>Your browser is {}</p>'.format(user_agent)
請求分派
應用收到客戶端發來的請求時,要找到處理該請求的視圖函數。為了完成這個任務,Flask 會在應用的 URL 映射中查找請求的 URL。URL 映射是 URL 和視圖函數之間的對應關系。Flask 使用 app.route 裝飾器構建映射。
要想查看 Flask 應用中的 URL 映射是什么樣子,可以在 Python shell 中審查為 app.py 生成的映射。測試之前,請確保你激活了虛擬環境:
(venv) $ python
>>> from app import app
>>> app.url_map
Map([<Rule '/' (HEAD, OPTIONS, GET) -> index>,
<Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>,
<Rule '/user/<name>' (HEAD, OPTIONS, GET) -> user>])
/ 和 /user/
URL 映射中的 (HEAD, OPTIONS, GET) 是請求方法,由路由進行處理。HTTP 規范中規定,每個請求都有對應的處理方法,這通常表示客戶端想讓服務器執行什么樣的操作。Flask 為每個路由都指定了請求方法,這樣即使不同的請求方法發送到相同的 URL 上時,也會使用不同的視圖函數處理。HEAD 和 OPTIONS 方法由 Flask 自動處理。
響應
Flask 調用視圖函數后,會將其返回值作為響應的內容。多數情況下,響應就是一個簡單的字符串,作為 HTML 頁面回送客戶端。
但 HTTP 協議需要的不僅是作為請求響應的字符串。HTTP 響應中一個很重要的部分是狀態碼,Flask 默認設為 200,表明請求已被成功處理。
如果視圖函數返回的響應需要使用不同的狀態碼,可以把數字代碼作為第二個返回值,添加到響應文本之后。例如,下述視圖函數返回 400 狀態碼,表示請求無效:
@app.route('/')
def index():
return '<h1>Bad Request</h1>', 400
如果不想返回由 1 個、2 個或 3 個值組成的元組,Flask 視圖函數還可以返回一個響應對象。make_response() 函數可接受 1 個、2 個或 3 個參數(和視圖函數的返回值一樣),然后返回一個等效的響應對象。有時我們需要在視圖函數中生成響應對象,然后在響應對象上調用各個方法,進一步設置響應。下例創建一個響應對象,然后設置 cookie:
from flask import make_response
@app.route('/')
def index():
response = make_response('<h1>This document carries a cookie!</h1>')
response.set_cookie('answer', '42')
return response
響應有個特殊的類型,稱為重定向。這種響應沒有頁面文檔,只會告訴瀏覽器一個新 URL,用以加載新頁面。
重定向的狀態碼通常是 302,在 Location 首部中提供目標 URL。
from flask import redirect
@app.route('/')
def index():
return redirect('http://www.example.com')
還有一種特殊的響應由 abort() 函數生成,用於處理錯誤。在下面這個例子中,如果 URL 中動態參數 id 對應的用戶不存在,就返回狀態碼 404:
from flask import abort
@app.route('/user/<id>')
def get_user(id):
user = load_user(id)
if not user:
abort(404)
return '<h1>Hello, {}</h1>'.format(user.name)
注意,abort() 不會把控制權交還給調用它的函數,而是拋出異常。