小白學Flask第八天| Flask上下文和請求鉤子
- 2019 年 10 月 4 日
- 筆記
本文內容:
1.Flask的上下文對象
2.請求鉤子
Flask的上下文對象
在這篇文章之前,我們學習過request和session這兩個小傢伙,他們兩的功能都非常的強大,我們今天講上下文對象,也是和他們兩有著很大的關係。
request:封裝了HTTP請求的內容,針對的是http請求。舉例:user = request.args.get('user'),獲取的是get請求的參數。
session:用來記錄請求會話中的資訊,針對的是用戶資訊。舉例:session['name'] = user.id,可以記錄用戶資訊。還可以通過session.get('name')獲取用戶資訊。
首先給大家看段程式碼:
from flask import Flask, request app = Flask(__name__) @app.route('/') def hello_world(request): # 在這裡將request對象作為參數傳進來 data = request.json return 'hello world' if __name__ == '__main__': app.run()
大家仔細看這段程式碼會發現我們將request對象作為參數傳進視圖函數hello_world,如果我們當真要這樣去使用request對象,視圖函數一多,我們就會發現這樣非常的不整潔而且還容易出錯。
為了解決這個問題,利用「上下文對象」將request對象作為全局變數,此時這個request對象就是在這個執行緒中的全局變數。但是如果這個對象是在A執行緒當中那麼他就是A執行緒中的全局變數,在其他執行緒(B執行緒,C執行緒…)當中不是全局變數,這樣就可以保證對象不會混淆。
所以我們平時這樣寫就OK了:
from flask import Flask, request app = Flask(__name__) @app.route('/') def hello_world(): data = request.json return 'hello world' if __name__ == '__main__': app.run()
session的道理也是類似的,這裡就不多闡述。
除了request和session這類請求上下文對象(request context),還有一類上下文對象,叫做應用上下文對象(application context)。
current_app和g都屬於應用上下文對象。
current_app : 表示當前運行程式文件的程式實例。
g : 處理請求時,用於臨時存儲的對象,每次請求都會重設這個變數。
current_app在之前的文章中我們也簡單介紹過。那麼g是啥?
其實它就是一個存儲容器,你想往裡面存儲什麼樣的數據都可以。
from flask import Flask,g app = Flask(__name__) @app.route('/') def hello_world(): g.username = "JavaandPython君" g.pass = "123" return 'hello world' if __name__ == '__main__': app.run()
請求鉤子
大家可能以前沒聽說過這個概念,其實非常容易理解,大家都知道鉤子是什麼,鉤子有什麼用呢? 鉤住某個東西然後跟它連在一起。
在客戶端和伺服器交互的過程中,有些準備工作或掃尾工作需要處理,比如:在請求開始時,建立資料庫連接;在請求結束時,指定數據的交互格式。為了讓每個視圖函數避免編寫重複功能的程式碼,Flask提供了通用設施的功能,即請求鉤子。
這裡給出幾個鉤子的概念:
1.before_first_request : 在第一次請求之前運行,只需執行一次,如鏈接資料庫
2.before_request : 在每一次請求都會執行,可以在這裡做許可權校驗操作,比如說某用戶是黑名單用戶,黑名單用戶登錄系統將遭到拒絕訪問,可以使用before_request進行許可權校驗。
3.after_request :在請求之後運行,會接收一個參數,這個參數就是前面的請求處理完畢之後, 返回的響應數據,如果需要對響應做額外處理,可以再這裡進行。
4.teardown_request :每一次請求之後都會調用,會接受一個參數,參數是伺服器出現的錯誤資訊
如何使用它們呢?其實也是非常簡單
from flask import Flask app = Flask(__name__) @app.route('/') def helloworld(): return 'hello world' # 在第一次請求之前運行. # 例子: 比如連接資料庫操作, 只需要執行一次 @app.before_first_request def before_first_request(): print('before_first_request') # 在每一次請求都會執行 # 例子: 可以在這裡做許可權校驗操作,比如說某用戶是黑名單用戶,黑名單用戶登錄系統將遭到拒絕訪問,可以使用 # before_request進行許可權校驗 @app.before_request def before_request(): print('before_request') # 在請求之後運行 @app.after_request def after_request(response): # response: 就是前面的請求處理完畢之後, 返回的響應數據 # 如果需要對響應做額外處理,可以再這裡進行 # json.dumps 配置請求鉤子 # response.headers["Content-Type"] = "application/json" print('after_request') return response # 每一次請求之後都會調用,會接受一個參數,參數是伺服器出現的錯誤資訊 @app.teardown_request def teardown_request(error): # 資料庫的擴展, 可以實現自動提交資料庫 print('teardown_request: error %s' % error) if __name__ == '__main__': app.run(debug=True)
關於鉤子的知識點,我們只需要去記住這幾個點就OK了。
但是這裡給大家延申一個知識,從上面大家可能會發現我們這些鉤子不能夠去鎖定某個視圖函數,例如他不能確定我只有運行A視圖函數才去執行鉤子里的內容,我運行B視圖函數他也會去執行,那麼怎樣才能夠指定視圖函數執行指定的鉤子內容。
from flask import Flask,url_for, request app = Flask(__name__) @app.route('/hello') def helloworld(): return 'hello world' @app.route('/index') def index(): return 'hello index' # 在第一次請求之前運行. # 例子: 比如連接資料庫操作, 只需要執行一次 @app.before_first_request def before_first_request(): path = request.path if path == url_for("hello"): printf("如果是hello視圖函數就執行這個") elif path == url_for("index"): printf("如果是index視圖函數就執行這個") return "" if __name__ == '__main__': app.run(debug=True)
通過上面程式碼,相信你就已經懂怎麼做了!
