欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Flask中特殊裝飾器的使用

 更新時間:2023年12月22日 09:18:51   作者:孤寒者  
在Flask中,before_request和after_request是用作裝飾器的特殊函數(shù),本文主要介紹了Flask中特殊裝飾器的使用,具有一定的參考價值,感興趣的可以了解一下

Flask中用作裝飾器的特殊的函數(shù) 第一部分:before_request和after_request

在Flask中,before_requestafter_request是用作裝飾器的特殊函數(shù),它們可以用來在請求處理過程中執(zhí)行某些操作。

一、 before_request裝飾器:

  • 通過在函數(shù)上使用@app.before_request裝飾器,可以將該函數(shù)注冊為全局的請求前鉤子(hook)。這意味著每次請求到達(dá)服務(wù)器時,在實(shí)際處理請求之前,都會先執(zhí)行被before_request裝飾的函數(shù)。
  • before_request函數(shù)通常用于執(zhí)行一些預(yù)處理任務(wù),例如驗(yàn)證用戶身份、設(shè)置全局變量、打開數(shù)據(jù)庫連接等。它可以修改請求或應(yīng)用程序上下文,并且可以返回響應(yīng)對象或 None(后面扒扒源碼看看)。

比如:

@app.before_request
def before_request():
    # 執(zhí)行一些預(yù)處理任務(wù)
    if not current_user.is_authenticated:
        return redirect(url_for('login'))

二、after_request裝飾器:

  • 通過在函數(shù)上使用@app.after_request裝飾器,可以將該函數(shù)注冊為全局的請求后鉤子。這意味著在每次請求完成并返回響應(yīng)之后,都會執(zhí)行被after_request裝飾的函數(shù)。
  • after_request函數(shù)通常用于執(zhí)行一些后處理任務(wù),例如**添加響應(yīng)頭、記錄請求日志、關(guān)閉數(shù)據(jù)庫連接等。**它接收一個參數(shù),即響應(yīng)對象,并且必須返回一個響應(yīng)對象。

比如:

@app.after_request
def after_request(response):
    # 執(zhí)行一些后處理任務(wù)
    response.headers['X-Frame-Options'] = 'SAMEORIGIN'
    return response

通過使用before_requestafter_request裝飾器,可以在請求的前后執(zhí)行一些共同的邏輯,從而實(shí)現(xiàn)全局的預(yù)處理和后處理操作。這樣可以避免在每個視圖函數(shù)中重復(fù)編寫相同的代碼。

三、多個before_request和after_request執(zhí)行流程分析:

首先—理論講解:

當(dāng)存在多個before_requestafter_request裝飾器時,分析它們的執(zhí)行順序:

before_request執(zhí)行流程:

  • 當(dāng)一個請求到達(dá)服務(wù)器時,首先會執(zhí)行第一個注冊before_request裝飾的函數(shù)。
  • 如果該函數(shù)返回了一個響應(yīng)對象,則停止執(zhí)行后續(xù)所有的before_request函數(shù),而是直接返回該響應(yīng)對象給客戶端。
  • 如果該函數(shù)沒有返回響應(yīng)對象,則繼續(xù)執(zhí)行下一個注冊的before_request函數(shù),以此類推,直到所有的before_request函數(shù)都被執(zhí)行完畢。

after_request執(zhí)行流程:

  • 在每次請求完成并返回響應(yīng)之后,從最后一個注冊after_request裝飾的函數(shù)開始執(zhí)行。
  • 每個after_request函數(shù)都會接收前一個after_request函數(shù)所返回的響應(yīng)對象作為參數(shù),并且必須返回一個新的響應(yīng)對象。
  • 執(zhí)行完最后一個after_request函數(shù)后,最終的響應(yīng)對象將會發(fā)送給客戶端。

然后—實(shí)戰(zhàn)講解:

from flask import Flask, session

app = Flask(__name__)  # 創(chuàng)建Flask應(yīng)用程序?qū)ο?


@app.before_request
def before_request_1():
    print("Before Request 1")


@app.before_request
def before_request_2():
    print("Before Request 2")


@app.after_request
def after_request_1(response):
    print("After Request 1")
    return response


@app.after_request
def after_request_2(response):
    print("After Request 2")
    return response


@app.route('/')
def index():
    print("Index Page")
    return "Hello, World!"


if __name__ == '__main__':
    app.run()

輸出的執(zhí)行順序如下:

可以看到,首先執(zhí)行了before_request_1before_request_2兩個函數(shù),然后處理了請求并返回響應(yīng),接著按照相反的順序執(zhí)行了after_request_2after_request_1兩個函數(shù)。

最后—扒扒源碼:

為何before_request是按注冊順序執(zhí)行,而after_request是按注冊倒序執(zhí)行嘞?

扒一扒源碼就曉得啦~

直接進(jìn)入before_requestafter_request的身體:

上面就是Flask注冊before_requestafter_request函數(shù)的方法,一模一樣!

下面來扒下Flask執(zhí)行before_requestafter_request函數(shù)部分的源碼:

進(jìn)入app.__call__()后直到full_dispatch_request函數(shù):

關(guān)注點(diǎn)先放在上圖第二個for循環(huán),其余部分后續(xù)會慢慢探究~

before_request_funcs 就是上述包含了請求前鉤子函數(shù)的字典。這些函數(shù)會在請求分發(fā)(即dispatch_request)之前被調(diào)用。

遍歷每個注冊的請求前鉤子函數(shù),并執(zhí)行它們。如果任何一個請求前鉤子函數(shù)**返回一個非 None 的值,該值會被當(dāng)作視圖函數(shù)的返回值處理(直接返回給客戶端頁面),并且后續(xù)的請求處理流程會被停止【但是after_request正常執(zhí)行!】;**如果沒有任何請求前鉤子函數(shù)返回非 None 值,那么 preprocess_request 方法會返回 None。

來個代碼講解:

畫圖形象記憶:

綠色就是所有請求前鉤子函數(shù)(before_request)返回值都為None時的執(zhí)行流程;

相應(yīng)的,白色就是有一個返回值非None時的執(zhí)行流程。

差點(diǎn)忘了帶大家看after_request了!

看到?jīng)]!reversed?。?!反向遍歷哦~

第二部分:實(shí)戰(zhàn)—使用before_request進(jìn)行身份驗(yàn)證

上代碼:

from flask import Flask, request, redirect, url_for, render_template, session

app = Flask(__name__)

# 模擬的用戶數(shù)據(jù)庫
users = {
    'admin': {
        'username': 'admin',
        'password': 'GuHanZhe'
    }
}


@app.before_request
def authenticate_user():
    # 獲取當(dāng)前請求的路徑
    path = request.path

    # 如果請求的路徑不是登錄頁面,進(jìn)行身份驗(yàn)證
    if path != '/login':
        # 檢查 session 中是否存在已登錄的用戶
        if 'username' not in session:
            # 用戶未登錄,重定向到登錄頁面
            return redirect(url_for('login'))


@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']

        # 在實(shí)際開發(fā)中,這里需要進(jìn)行密碼驗(yàn)證
        if username in users and users[username]['password'] == password:
            # 登錄成功,將用戶名保存在 session 中
            session['username'] = username
            return redirect(url_for('protected_page'))
        else:
            # 登錄失敗,顯示錯誤信息
            error_message = "Invalid username or password."
            return render_template('login.html', error_message=error_message)

    return render_template('login.html')


@app.route('/protected')
def protected_page():
    return "This is a protected page. Only logged-in users can access it."


if __name__ == '__main__':
    app.run()

在上述代碼中,before_request 鉤子函數(shù) authenticate_user 用于驗(yàn)證用戶身份。它會在每個請求到達(dá)之前被調(diào)用,除了登錄頁面 /login 外的所有頁面都需要進(jìn)行身份驗(yàn)證。

如果用戶未登錄,authenticate_user 函數(shù)將重定向到登錄頁面,使用 redirect 函數(shù)和 url_for 函數(shù)實(shí)現(xiàn)頁面重定向。登錄成功后,將用戶名保存在 session 中,以便在后續(xù)的請求中進(jìn)行驗(yàn)證。

login 路由處理函數(shù)負(fù)責(zé)渲染登錄頁面,并接收用戶提交的表單數(shù)據(jù)。在實(shí)際應(yīng)用中,需要根據(jù)數(shù)據(jù)庫中的用戶信息進(jìn)行密碼驗(yàn)證。驗(yàn)證成功后,將用戶名保存在 session 中,并重定向到受保護(hù)的頁面 /protected。

protected_page 路由處理函數(shù)是一個示例的受保護(hù)頁面,只有登錄用戶可見。

第三部分:補(bǔ)充常見特殊裝飾器

一、@app.errorhandler(code):

  • 這是用于注冊錯誤處理函數(shù)的裝飾器。
  • code 參數(shù)指定了需要處理的錯誤碼,例如 404、500 等。
  • 裝飾的函數(shù)將作為錯誤處理函數(shù),在出現(xiàn)指定錯誤碼時被調(diào)用,并返回自定義的錯誤頁面或響應(yīng)。

二、 @app.teardown_request:

用于注冊在每個請求結(jié)束時執(zhí)行的函數(shù)。它可以用來進(jìn)行一些清理操作或釋放資源。

實(shí)戰(zhàn):

from flask import Flask

app = Flask(__name__)


@app.route('/')
def index():
    return "Hello, World!"


@app.teardown_request
def teardown_request_func(error=None):
    print("Teardown function is called after each request.")


if __name__ == '__main__':
    app.run()

在上述代碼中,定義了一個名為 teardown_request_func 的函數(shù),并使用 @app.teardown_request 裝飾器將其注冊為每個請求結(jié)束時執(zhí)行的函數(shù)。

當(dāng)我們訪問任何路由時,F(xiàn)lask 會在請求結(jié)束后自動調(diào)用 teardown_request_func 函數(shù)。無論請求是否出現(xiàn)錯誤,該函數(shù)都會被執(zhí)行。

需要注意的是,@app.teardown_request 裝飾的函數(shù)只能接受一個參數(shù),即可選的錯誤對象。如果要訪問請求上下文中的其他對象,可以使用 flask.request 對象。

這個裝飾器通常用于進(jìn)行一些清理操作,例如關(guān)閉數(shù)據(jù)庫連接、釋放資源等。

三、@app.template_test:

用于注冊自定義模板測試函數(shù)的裝飾器。

實(shí)戰(zhàn):

from flask import Flask

app = Flask(__name__)


@app.template_test('even')
def is_even(number):
    return number % 2 == 0


if __name__ == '__main__':
    app.run()

通過 @app.template_test('even') 裝飾器將 is_even 函數(shù)注冊為一個名為 “even” 的模板測試函數(shù)。該函數(shù)用于判斷一個數(shù)字是否是偶數(shù)。

在模板中,可以使用 {% if %} 語句來調(diào)用這個模板測試函數(shù):

{% if num is even %}
    <p>The number is even</p>
{% else %}
    <p>The number is odd</p>
{% endif %}

通過注冊模板測試函數(shù),我們可以在模板中使用自定義的邏輯判斷函數(shù),以便根據(jù)特定的條件進(jìn)行動態(tài)渲染和顯示不同的內(nèi)容。

四、@app.before_first_request:

用于注冊在第一個請求到達(dá)之前執(zhí)行的函數(shù)。它只會在應(yīng)用程序啟動時執(zhí)行一次。

實(shí)戰(zhàn):

from flask import Flask

app = Flask(__name__)


@app.before_first_request
def before_first_request_func():
    print("This function is executed before the first request.")


@app.route('/')
def index():
    return "Hello, World!"


if __name__ == '__main__':
    app.run()

在上述代碼中,before_first_request_func 被裝飾為 @app.before_first_request,它會在第一個請求到達(dá)之前執(zhí)行。

當(dāng)我們運(yùn)行這個應(yīng)用程序時,before_first_request_func 函數(shù)會在第一個請求到達(dá)之前執(zhí)行一次。之后,每個請求到達(dá)時,都不會再次調(diào)用該函數(shù)。

需要注意的是,@app.before_first_request 裝飾的函數(shù)僅在主線程中執(zhí)行,并且只有在應(yīng)用程序啟動時才會被調(diào)用一次。如果使用多線程或多進(jìn)程部署應(yīng)用程序,可以考慮使用其他方法來進(jìn)行初始化操作。

【新版本Flask沒有這個裝飾器了~】

到此這篇關(guān)于Flask中特殊裝飾器的使用的文章就介紹到這了,更多相關(guān)Flask 特殊裝飾器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:

相關(guān)文章

  • python實(shí)現(xiàn)協(xié)同過濾推薦算法完整代碼示例

    python實(shí)現(xiàn)協(xié)同過濾推薦算法完整代碼示例

    這篇文章主要介紹了python實(shí)現(xiàn)協(xié)同過濾推薦算法完整代碼示例,具有一定借鑒價值,需要的朋友可以參考下。
    2017-12-12
  • spark: RDD與DataFrame之間的相互轉(zhuǎn)換方法

    spark: RDD與DataFrame之間的相互轉(zhuǎn)換方法

    今天小編就為大家分享一篇spark: RDD與DataFrame之間的相互轉(zhuǎn)換方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-06-06
  • Python使用正則表達(dá)式實(shí)現(xiàn)爬蟲數(shù)據(jù)抽取

    Python使用正則表達(dá)式實(shí)現(xiàn)爬蟲數(shù)據(jù)抽取

    這篇文章主要介紹了Python使用正則表達(dá)式實(shí)現(xiàn)爬蟲數(shù)據(jù)抽取,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • Python?sklearn?中的?make_blobs()?函數(shù)示例詳解

    Python?sklearn?中的?make_blobs()?函數(shù)示例詳解

    make_blobs()?是?sklearn.datasets中的一個函數(shù),這篇文章主要介紹了Python?sklearn?中的?make_blobs()?函數(shù),本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-02-02
  • python?pygame實(shí)現(xiàn)打磚塊游戲

    python?pygame實(shí)現(xiàn)打磚塊游戲

    這篇文章主要為大家詳細(xì)介紹了python?pygame實(shí)現(xiàn)打磚塊游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • Python繪制時鐘的示例代碼

    Python繪制時鐘的示例代碼

    這篇文章主要介紹了如何利用Python和Pygame庫繪制一個簡單的時鐘效果。文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)Python有一定幫助,需要的可以參考一下
    2022-02-02
  • 去除python中的字符串空格的簡單方法

    去除python中的字符串空格的簡單方法

    在本篇文章里小編給大家整理了一篇關(guān)于去除python中的字符串空格的簡單方法,有興趣的朋友們可以學(xué)習(xí)下。
    2020-12-12
  • Django-xadmin+rule對象級權(quán)限的實(shí)現(xiàn)方式

    Django-xadmin+rule對象級權(quán)限的實(shí)現(xiàn)方式

    今天小編就為大家分享一篇Django-xadmin+rule對象級權(quán)限的實(shí)現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-03-03
  • pycharm新建Vue項(xiàng)目的方法步驟(圖文)

    pycharm新建Vue項(xiàng)目的方法步驟(圖文)

    這篇文章主要介紹了pycharm新建Vue項(xiàng)目的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • Python字節(jié)串類型bytes及用法

    Python字節(jié)串類型bytes及用法

    這篇文章介紹了Python字節(jié)串類型bytes及用法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-05-05

最新評論