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

Flask中特殊裝飾器的使用

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

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

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

一、 before_request裝飾器:

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

比如:

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

二、after_request裝飾器:

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

比如:

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

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

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

首先—理論講解:

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

before_request執(zhí)行流程:

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

after_request執(zhí)行流程:

  • 在每次請(qǐng)求完成并返回響應(yīng)之后,從最后一個(gè)注冊(cè)after_request裝飾的函數(shù)開(kāi)始執(zhí)行。
  • 每個(gè)after_request函數(shù)都會(huì)接收前一個(gè)after_request函數(shù)所返回的響應(yīng)對(duì)象作為參數(shù),并且必須返回一個(gè)新的響應(yīng)對(duì)象。
  • 執(zhí)行完最后一個(gè)after_request函數(shù)后,最終的響應(yīng)對(duì)象將會(huì)發(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兩個(gè)函數(shù),然后處理了請(qǐng)求并返回響應(yīng),接著按照相反的順序執(zhí)行了after_request_2after_request_1兩個(gè)函數(shù)。

最后—扒扒源碼:

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

扒一扒源碼就曉得啦~

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

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

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

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

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

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

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

來(lái)個(gè)代碼講解:

畫(huà)圖形象記憶:

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

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

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

看到?jīng)]!reversed?。。》聪虮闅v哦~

第二部分:實(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ù)庫(kù)
users = {
    'admin': {
        'username': 'admin',
        'password': 'GuHanZhe'
    }
}


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

    # 如果請(qǐng)求的路徑不是登錄頁(yè)面,進(jìn)行身份驗(yàn)證
    if path != '/login':
        # 檢查 session 中是否存在已登錄的用戶
        if 'username' not in session:
            # 用戶未登錄,重定向到登錄頁(yè)面
            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í)際開(kāi)發(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:
            # 登錄失敗,顯示錯(cuò)誤信息
            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)證用戶身份。它會(huì)在每個(gè)請(qǐng)求到達(dá)之前被調(diào)用,除了登錄頁(yè)面 /login 外的所有頁(yè)面都需要進(jìn)行身份驗(yàn)證。

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

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

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

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

一、@app.errorhandler(code):

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

二、 @app.teardown_request:

用于注冊(cè)在每個(gè)請(qǐng)求結(jié)束時(shí)執(zhí)行的函數(shù)。它可以用來(lái)進(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()

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

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

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

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

三、@app.template_test:

用于注冊(cè)自定義模板測(cè)試函數(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()

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

在模板中,可以使用 {% if %} 語(yǔ)句來(lái)調(diào)用這個(gè)模板測(cè)試函數(shù):

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

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

四、@app.before_first_request:

用于注冊(cè)在第一個(gè)請(qǐng)求到達(dá)之前執(zhí)行的函數(shù)。它只會(huì)在應(yīng)用程序啟動(dòng)時(shí)執(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,它會(huì)在第一個(gè)請(qǐng)求到達(dá)之前執(zhí)行。

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

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

【新版本Flask沒(méi)有這個(gè)裝飾器了~】

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

您可能感興趣的文章:

相關(guān)文章

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

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

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

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

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

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

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

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

    make_blobs()?是?sklearn.datasets中的一個(gè)函數(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ì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • Python繪制時(shí)鐘的示例代碼

    Python繪制時(shí)鐘的示例代碼

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

    去除python中的字符串空格的簡(jiǎn)單方法

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

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

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

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

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

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

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

最新評(píng)論