小白學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)

通過上面程式碼,相信你就已經懂怎麼做了!