一、程序上下文
Flask接收到來自客戶端的請求后,路由到指定的接口進行響應處理並返回處理結果。響應接口需要知道客戶端的請求體,即request對象才能進行正確的處理。如果給每個接口函數都傳遞一個request對象參數,太過冗余,且代碼會很難看,因此Flask使用上下文臨時將某些對象編程線程內的全局變量,即在同一個線程內,上下文信息可全局共享,且不會干擾到其他的線程環境。
Flask有兩種上下文,分別為程序上下文和請求上下文,各自對應的全局變量如下表:
| 變量名 | 上下文 | 備注 |
| current_app | 程序上下文 | 表示當前運行的程序實例 |
| g | 程序上下文 | 處理請求時用作臨時存儲對象,每次請求都會重新設值 |
| request | 請求上下文 | 客戶端發來的request請求對象 |
| session | 請求上下文 | 請求攜帶的會話信息 |
Flask在分發請求之前會激活上下文信息,在請求處理完成后再刪除。上下文只有在激活后,才可使用對應的全局變量,否則會報異常。
app_ctx = app.app_context() #可獲取app對應的上下文
app_ctx.push() #推送上下文信息,即激活上下文
二、請求鈎子
有時候,在請求開始或結束后,我們可能想要執行一些代碼,比如,在請求開始前,完成數據庫的連接,用戶信息的認證等等。Flask使用裝飾器為我們提供了注冊通用函數的功能,支持的鈎子函數有以下四種:
| before_first_request | 第一次請求之前調用 |
| before_request | 每次請求之前調用 |
| after_request | 每次請求之后調用,前提是沒有未處理的異常拋出 |
| teardown_request | 每次請求之后調用,即使有未處理的異常拋出 |
在請求函數和鈎子函數之間,一般通過全局變量g實現數據共享。
三、響應
Flask的響應一般可包含三個參數,第一個參數指明響應的字符串,第二個參數可指明響應狀態碼,如200表示響應成功,第三個參數是由header首部組成的字典。我們可以通過make_response()生成一個response對象並設置。
1 #!/usr/bin/env python 2 # encoding: utf-8 3 from flask import Flask 4 from flask import request 5 6 app = Flask(__name__) 7 8 9 @app.route('/') 10 def hello_world(): 11 return 'Hello World!' 12 13 14 @app.route("/user/<user_name>") 15 def hello_user(user_name): 16 """ 17 動態路由示例 18 :param user_name: 用戶名 19 :return: 20 """ 21 1/0 22 return "Hello %s" % user_name 23 24 25 @app.route("/context") 26 def get_context(): 27 """ 28 獲取請求的上下文信息 29 :return: 30 """ 31 user_agent = request.headers.get("user-agent") 32 return "your user-agent is %s" % user_agent 33 34 35 @app.before_first_request 36 def first_quest(): 37 print "run before first request" 38 39 40 @app.before_request 41 def every_request(): 42 print "One new request is comming" 43 44 45 @app.after_request 46 def after_r(exception): 47 print "The request has done 1" 48 49 @app.teardown_request 50 def teardown_r(exception): 51 print "The request has done 2" 52 53 54 if __name__ == '__main__': 55 app.run()
上述代碼運行后,在瀏覽器分別請求
http://127.0.0.1:5000/ 輸出:
run before first request
One new request is comming
The request has done 1
The request has done 2
http://127.0.0.1:5000/user/patty 輸出:
One new request is comming
The request has done 2
變量共享:通過g實現
1 @app.route('/') 2 def hello_world(): 3 print g.user 4 return 'Hello World!' 5 6 @app.before_first_request 7 def first_quest(): 8 g.user = 'tmp' 9 print "run before first request"
