0


(十三)Flask之特殊装饰器详解

目录:

Flask中用作装饰器的特殊的函数

第一部分:

before_request

after_request

在Flask中,

before_request

after_request

是用作装饰器的特殊函数,它们可以用来在请求处理过程中执行某些操作。

一、

before_request

装饰器:

  • 通过在函数上使用@app.before_request装饰器,可以将该函数注册为全局的请求前钩子(hook)。这意味着每次请求到达服务器时,在实际处理请求之前,都会先执行被before_request装饰的函数。
  • before_request函数通常用于执行一些预处理任务,例如验证用户身份、设置全局变量、打开数据库连接等。它可以修改请求或应用程序上下文,并且可以返回响应对象或 None(后面扒扒源码看看)。

比如:

@app.before_requestdefbefore_request():# 执行一些预处理任务ifnot current_user.is_authenticated:return redirect(url_for('login'))

二、

after_request

装饰器:

  • 通过在函数上使用@app.after_request装饰器,可以将该函数注册为全局的请求后钩子。这意味着在每次请求完成并返回响应之后,都会执行被after_request装饰的函数。
  • after_request函数通常用于执行一些后处理任务,例如添加响应头、记录请求日志、关闭数据库连接等。它接收一个参数,即响应对象,并且必须返回一个响应对象。

比如:

@app.after_requestdefafter_request(response):# 执行一些后处理任务
    response.headers['X-Frame-Options']='SAMEORIGIN'return response

通过使用

before_request

after_request

装饰器,可以在请求的前后执行一些共同的逻辑,从而实现全局的预处理和后处理操作。这样可以避免在每个视图函数中重复编写相同的代码。

三、多个

before_request

after_request

执行流程分析:

首先—理论讲解:

当存在多个

before_request

after_request

装饰器时,分析它们的执行顺序:

  1. before_request执行流程:- 当一个请求到达服务器时,首先会执行第一个注册before_request装饰的函数。- 如果该函数返回了一个响应对象,则停止执行后续所有的before_request函数,而是直接返回该响应对象给客户端。- 如果该函数没有返回响应对象,则继续执行下一个注册的before_request函数,以此类推,直到所有的before_request函数都被执行完毕。
  2. after_request执行流程:- 在每次请求完成并返回响应之后,从最后一个注册after_request装饰的函数开始执行。- 每个after_request函数都会接收前一个after_request函数所返回的响应对象作为参数,并且必须返回一个新的响应对象。- 执行完最后一个after_request函数后,最终的响应对象将会发送给客户端。
然后—实战讲解:
from flask import Flask, session

app = Flask(__name__)# 创建Flask应用程序对象@app.before_requestdefbefore_request_1():print("Before Request 1")@app.before_requestdefbefore_request_2():print("Before Request 2")@app.after_requestdefafter_request_1(response):print("After Request 1")return response

@app.after_requestdefafter_request_2(response):print("After Request 2")return response

@app.route('/')defindex():print("Index Page")return"Hello, World!"if __name__ =='__main__':
    app.run()

输出的执行顺序如下:

在这里插入图片描述

可以看到,首先执行了

before_request_1

before_request_2

两个函数,然后处理了请求并返回响应,接着按照相反的顺序执行了

after_request_2

after_request_1

两个函数。

最后—扒扒源码:

为何

before_request

是按注册顺序执行,而

after_request

是按注册倒序执行嘞?

扒一扒源码就晓得啦~

直接进入

before_request

after_request

的身体:

在这里插入图片描述

上面就是Flask注册

before_request

after_request

函数的方法,一模一样!

下面来扒下Flask执行

before_request

after_request

函数部分的源码:

进入

app.__call__()

后直到

full_dispatch_request

函数:

在这里插入图片描述

在这里插入图片描述

关注点先放在上图第二个for循环,其余部分后续会慢慢探究~

before_request_funcs

就是上述包含了请求前钩子函数的字典。这些函数会在请求分发(即

dispatch_request

)之前被调用。

遍历每个注册的请求前钩子函数,并执行它们。如果任何一个请求前钩子函数返回一个非 None 的值,该值会被当作视图函数的返回值处理(直接返回给客户端页面),并且后续的请求处理流程会被停止【但是after_request正常执行!】;如果没有任何请求前钩子函数返回非 None 值,那么

preprocess_request

方法会返回 None。

来个代码讲解:

在这里插入图片描述
在这里插入图片描述

画图形象记忆:

绿色就是所有请求前钩子函数(

before_request

)返回值都为None时的执行流程;

相应的,白色就是有一个返回值非None时的执行流程。
在这里插入图片描述

差点忘了带大家看

after_request

了!

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

看到没!reversed!!!反向遍历哦~

第二部分:实战—使用

before_request

进行身份验证

上代码:

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

app = Flask(__name__)# 模拟的用户数据库
users ={'admin':{'username':'admin','password':'GuHanZhe'}}@app.before_requestdefauthenticate_user():# 获取当前请求的路径
    path = request.path

    # 如果请求的路径不是登录页面,进行身份验证if path !='/login':# 检查 session 中是否存在已登录的用户if'username'notin session:# 用户未登录,重定向到登录页面return redirect(url_for('login'))@app.route('/login', methods=['GET','POST'])deflogin():if request.method =='POST':
        username = request.form['username']
        password = request.form['password']# 在实际开发中,这里需要进行密码验证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')defprotected_page():return"This is a protected page. Only logged-in users can access it."if __name__ =='__main__':
    app.run()

在上述代码中,

before_request

钩子函数

authenticate_user

用于验证用户身份。它会在每个请求到达之前被调用,除了登录页面

/login

外的所有页面都需要进行身份验证。

如果用户未登录,

authenticate_user

函数将重定向到登录页面,使用

redirect

函数和

url_for

函数实现页面重定向。登录成功后,将用户名保存在

session

中,以便在后续的请求中进行验证。

login

路由处理函数负责渲染登录页面,并接收用户提交的表单数据。在实际应用中,需要根据数据库中的用户信息进行密码验证。验证成功后,将用户名保存在

session

中,并重定向到受保护的页面

/protected

protected_page

路由处理函数是一个示例的受保护页面,只有登录用户可见。

第三部分:补充常见特殊装饰器

一、

@app.errorhandler(code)

  • 这是用于注册错误处理函数的装饰器。
  • code 参数指定了需要处理的错误码,例如 404、500 等。
  • 装饰的函数将作为错误处理函数,在出现指定错误码时被调用,并返回自定义的错误页面或响应。

二、

@app.teardown_request

用于注册在每个请求结束时执行的函数。它可以用来进行一些清理操作或释放资源。

实战:

from flask import Flask

app = Flask(__name__)@app.route('/')defindex():return"Hello, World!"@app.teardown_requestdefteardown_request_func(error=None):print("Teardown function is called after each request.")if __name__ =='__main__':
    app.run()

在上述代码中,定义了一个名为

teardown_request_func

的函数,并使用

@app.teardown_request

装饰器将其注册为每个请求结束时执行的函数。

当我们访问任何路由时,Flask 会在请求结束后自动调用

teardown_request_func

函数。无论请求是否出现错误,该函数都会被执行。

需要注意的是,

@app.teardown_request

装饰的函数只能接受一个参数,即可选的错误对象。如果要访问请求上下文中的其他对象,可以使用

flask.request

对象。

这个装饰器通常用于进行一些清理操作,例如关闭数据库连接、释放资源等。

三、

@app.template_test

用于注册自定义模板测试函数的装饰器。

实战:

from flask import Flask

app = Flask(__name__)@app.template_test('even')defis_even(number):return number %2==0if __name__ =='__main__':
    app.run()

通过

@app.template_test('even')

装饰器将

is_even

函数注册为一个名为 “even” 的模板测试函数。该函数用于判断一个数字是否是偶数。

在模板中,可以使用

{% if %}

语句来调用这个模板测试函数:

{% if num is even %}
    <p>The number is even</p>
{% else %}
    <p>The number is odd</p>
{% endif %}
通过注册模板测试函数,我们可以在模板中使用自定义的逻辑判断函数,

以便根据特定的条件进行动态渲染和显示不同的内容。

四、

@app.before_first_request

用于注册在第一个请求到达之前执行的函数。它只会在应用程序启动时执行一次。

实战:

from flask import Flask

app = Flask(__name__)@app.before_first_requestdefbefore_first_request_func():print("This function is executed before the first request.")@app.route('/')defindex():return"Hello, World!"if __name__ =='__main__':
    app.run()

在上述代码中,

before_first_request_func

被装饰为

@app.before_first_request

,它会在第一个请求到达之前执行。

当我们运行这个应用程序时,

before_first_request_func

函数会在第一个请求到达之前执行一次。之后,每个请求到达时,都不会再次调用该函数。

需要注意的是,

@app.before_first_request

装饰的函数仅在主线程中执行,并且只有在应用程序启动时才会被调用一次。如果使用多线程或多进程部署应用程序,可以考虑使用其他方法来进行初始化操作。

【新版本Flask没有这个装饰器了~】

标签: flask python 后端

本文转载自: https://blog.csdn.net/qq_44907926/article/details/134648895
版权归原作者 孤寒者 所有, 如有侵权,请联系我们删除。

“(十三)Flask之特殊装饰器详解”的评论:

还没有评论