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

第一部分:before_requestafter_request

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

一、 before_request装饰器:

比如

@app.before_request
def before_request():
    # 执行一些预处理任务
    if not current_user.is_authenticated:
        return redirect(url_for('login'))

二、after_request装饰器:

比如

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

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

三、多个before_requestafter_request执行流程分析

首先—理论讲解

存在多个before_requestafter_request装饰器时,分析它们的执行顺序

  1. before_request执行流程

  2. after_request执行流程

    • 在每次请求完成并返回响应之后,最后一个注册after_request装饰的函数开始执行。
    • 每个after_request函数都会接收前一个after_request函数所返回的响应对象作为参数,并且必须返回一个新的响应对象
    • 执行完最后一个after_request函数后,最终的响应对象将会发送客户端
然后实战讲解
from flask import Flask, session

app = Flask(__name__)  # 创建Flask应用程序对象


@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()

输出的执行顺序如下:

在这里插入图片描述

可以看到,首先执行了before_request_1before_request_2两个函数,然后处理了请求并返回响应,接着按照相反的顺序执行了after_request_2after_request_1两个函数。

最后—扒扒源码

为何before_request是按注册顺序执行,而after_request是按注册倒序执行嘞?

扒一扒源码就晓得啦~

直接进入before_requestafter_request的身体:

在这里插入图片描述

上面就是Flask注册before_requestafter_request函数的方法,一模一样!

下面来扒下Flask执行before_requestafter_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_request
def authenticate_user():
    # 获取当前请求的路径
    path = request.path

    # 如果请求的路径不是登录页面,进行身份验证
    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']

        # 在实际开发中,这里需要进行密码验证
        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 钩子函数 authenticate_user 用于验证用户身份。它会在每个请求到达之前被调用,除了登录页面 /login 外的所有页面需要进行身份验证

如果用户未登录,authenticate_user 函数将重定向到登录页面,使用 redirect 函数和 url_for 函数实现页面重定向。登录成功后,将用户名保存session 中,以便在后续的请求中进行验证

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

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

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

一、@app.errorhandler(code)

二、 @app.teardown_request

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

实战

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 的函数,并使用 @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')
def is_even(number):
    return number % 2 == 0


if __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_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,它会在第一个请求到达之前执行。

我们运行这个应用程序时,before_first_request_func 函数会在第一个请求到达之前执行一次之后,每个请求到达时,都不会再次调用该函数。

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

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

原文地址:https://blog.csdn.net/qq_44907926/article/details/134648895

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。

如若转载,请注明出处:http://www.7code.cn/show_13261.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注