【7.0】Flask框架之请求扩展

发布时间 2023-08-26 21:47:26作者: Chimengmeng

【一】请求扩展引入

  • 在 Flask 框架中,可以通过请求扩展(Request Extension)来实现类似于 Django 中间件的功能。
  • 请求扩展提供了一些钩子函数,可以在请求的不同生命周期中执行特定的操作。
  • 以下是 Flask 中几个常用的请求扩展和它们的作用:
    • before_request:在每个请求到达视图函数之前调用。
    • after_request:在每个请求结束后调用,并且只有在没有未处理的异常时才会调用。
    • before_first_request:在处理第一个请求之前调用,可用于初始化应用程序。
    • teardown_request:在每个请求结束后调用,无论是否有异常发生。
    • errorhandler:用于处理指定异常的错误处理函数。
    • template_global:注册一个全局函数,可以在模板中使用。
    • template_filter:注册一个自定义过滤器,可以在模板中使用。

【二】扩展方法详解

【1】before_request:

@app.before_request
def before_request_func():
    # 在每个请求到达视图函数之前执行的代码
    pass
  • 在上述示例中,before_request 装饰器将一个函数注册为 before_request 扩展的处理函数。
  • 在每个请求到达视图函数之前,该函数将被调用执行。
from flask import Flask, request

app = Flask(__name__)
app.debug = True


@app.route('/', methods=['GET', 'POST'])
def index():
    return 'index'


@app.route('/home', methods=['GET', 'POST'])
def home():
    return 'home'


# 请求扩展
# 请求来了执行---》process_request--->可以下多个,从上往下依次执行
@app.before_request
def before_request_func():
    # 当次请求的对象就是request
    # 【1】判断访问的不同路径
    if request.path == '/':
        print('访问根路径')
    else:
        print('访问其他路径')
    # 【2】判断如果是跟路径,向request对象中放个name,其他不放
    if request.path == '/':
        request.name = 'dream'
    else:
        print('访问其他路径')

    # 【3】返回None,会执行下一个请求扩展,如果返回4件套,直接就返回了,不再往下执行了
    if request.path == '/':
        return '不让你访问'
    else:
        print('访问其他路径')
    # 4 多个before_request,从上往下执行
    print('1111')


@app.before_request
def before2():
    print('2222')


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

【2】after_request:

@app.after_request
def after_request_func(response):
    # 在每个请求结束后调用的代码
    return response
  • 上述代码中,after_request 装饰器用于注册一个函数作为 after_request 扩展的处理函数。
  • 这个处理函数会在每个请求结束后调用,并且可以对响应进行处理(如修改、添加额外的响应头等),然后将响应返回。
@app.after_request
def after_request_func(response):
    # response :正常响应对象
    # 【1】可以用来处理跨域
    # 【2】请求进入 从上至下执行 after_request 方法
    # 请求离开 从下至上执行 after_request 方法
    print('走了走了222')
    # 一定要返回response
    return response

【3】before_first_request:

@app.before_first_request
def before_first_request_func():
    # 在处理第一个请求之前执行的代码
    pass
  • 在上述示例中,before_first_request 装饰器用于注册一个函数作为 before_first_request 扩展的处理函数。
  • 这个处理函数会在处理第一个请求之前执行一次,比如用于初始化应用程序。
# 项目运行起来的第一次会执行,以后再也不执行了
# 1.x可以,2.x弃用了

【4】teardown_request:

@app.teardown_request
def teardown_request_func(exception):
    # 在每个请求结束后调用的代码,无论是否有异常发生
    pass
  • 在上述示例中,teardown_request 装饰器用于注册一个函数作为 teardown_request 扩展的处理函数。
  • 这个处理函数会在每个请求结束后调用,而且无论是否有异常发生都会调用。
# teardown_request 每一个请求之后绑定一个函数,即使遇到了异常,也会执行
# 一般用来记录日志--->不能做统一异常处理
@app.teardown_request
def teardown_request_func(e):
    # 通过判断e是否为空,记录日志
    print(e)  # 出了异常,e就是异常对象,如果没有异常,e就是None
    print('来了老弟')
    if e:
        return '出异常了'

【5】errorhandler:

@app.errorhandler(500)
def server_error(error):
    # 特定异常的错误处理逻辑
    return 'Internal Server Error', 500
  • 上述代码中,errorhandler 装饰器用于注册一个函数作为 errorhandler 扩展的处理函数。
  • 这个函数将处理特定异常(例如 HTTP 500 Internal Server Error),并返回相应的错误消息和状态码。
## errorhandler : 可以用来处理全局异常
@app.errorhandler(404)
def server_error(e):
    print(e)
    print('xxx')
    return render_template('error.html')


@app.errorhandler(500)
def server_error1(e):
    print(e)
    print('500')
    return jsonify({'code': 999, 'msg': '服务器内部错误,请联系系统管理员'})

【6】template_global:

@app.template_global()
def format_time(dt):
    # 在模板中使用的全局函数,格式化时间
    return dt.strftime('%Y-%m-%d %H:%M:%S')
  • 上述示例中,template_global 装饰器用于注册一个函数作为全局函数,在模板中可以使用 {{ format_time(dt) }} 的形式调用该函数。
# template_global 全局标签,所有页面都可以用
@app.template_global()
def add(a1, a2):
    return a1 + a2
<h2>使用全局标签</h2>
{{add(4,5)}}

【7】template_filter:

@app.template_filter()
def reverse_string(s):
    # 在模板中使用的自定义过滤器,反转字符串
    return s[::-1]
  • 在上述示例中,template_filter 装饰器用于注册一个函数作为自定义过滤器,在模板中可以使用 {{ str|reverse_string }} 的形式调用该过滤器。
# template_filter 全局过滤器
@app.template_filter()
def db(a1, a2, a3):
    print(a1)
    return a1 + a2 + a3
<h2>使用全局过滤器</h2>

{{4|db(5,6)}}

【8】完整的示例

from flask import Flask, render_template

app = Flask(__name__)

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

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

@app.before_first_request
defardown_request
def teardown_request_func(exception):
    print("Teardown Request")

@app.errorhandler(500)
def server_error(error):
    return 'Internal Server Error', 500

@app.template_global()
def format_time(dt):
    return dt.strftime('%Y-%m-%d %H:%M:%S')

@app.template_filter()
def reverse_string(s):
    return s[::-1]

@app.route('/')
def index():
    return render_template('index.html', current_time=datetime.now())

if __name__ == '__main__':
    app.run()
  • 在上述示例中,我们分别定义了几个请求扩展对应的处理函数,并进行了相应的设置。
  • 当请求到达时,这些函数将按照定义的顺序被调用执行。
  • 同时也定义了一个使用全局函数和自定义过滤器的模板文件 index.html