跳至主要內容

请求钩子

Mr.Liu大约 2 分钟

请求钩子

概念

什么是请求钩子?

在客户端和服务器交互的过程中,有些准备工作或扫尾工作需要统一处理,为了让每个视图函数避免编写重复功能的代码,flask提供了统一的接口可以添加这些处理函数,即请求钩子

flask的请求钩子类似于Django的中间件, flask的请求钩子分为四种, 如下所示:

  • before_first_request: 请求处理前执行, 只执行一次
  • before_request: 请求处理前执行, 每次请求处理前都会执行
  • after_request: 请求处理后执行, 但其是在请求无异常的基础上执行的, 该钩子接受一个参数为响应对象, 并且钩子函数最后需要将参数传递来的响应return返回
  • teardown_request: 请求处理后执行, 其无论请求是否存在异常都会执行, 该钩子也接受一个参数为异常信息
from flask import Flask

app = Flask(__name__)


@app.route('/')
def helloworld():
    return 'hello world'


# 在第一次请求之前运行.
# 例子: 比如连接数据库操作, 只需要执行一次
@app.before_first_request
def before_first_request():
    print('before_first_request')


# 在每一次请求都会执行
# 例子: 可以在这里做权限校验操作,比如说某用户是黑名单用户,黑名单用户登录系统将遭到拒绝访问,可以使用 before_request进行权限校验
@app.before_request
def before_request():
    print('before_request')


# 在请求之后运行
@app.after_request
def after_request(response):
    # response: 就是前面的请求处理完毕之后, 返回的响应数据
    # 如果需要对响应做额外处理,可以再这里进行
    # 例子:在响应头中,配置响应类型
    # response.headers["Content-Type"] = "application/json"
    print('after_request')
    return response


# 每一次请求之后都会调用,会接受一个参数,参数是服务器出现的错误信息
@app.teardown_request
def teardown_request(error):
    # 数据库的扩展, 可以实现自动提交数据库
    print('teardown_request: error %s' % error)


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

案例演示

使用请求钩子实现用户权限的判断

from flask import Flask, request, make_response, redirect
import json

app = Flask(__name__)


@app.route('/')
def index():
    return 'hello goods'


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

    if username == 'admin' and password == '123':
        resp = make_response({'msg': '登录成功'}, 200)
        resp.set_cookie('username', 'admin')
        return resp

    else:
        return {'msg': '登录失败'}, 400


@app.route('/goods')
def goods():
    goods = {
        "id": 1,
        "name": "华为P40"
    }
    return json.dumps(goods)


# 在每一次请求都会执行,判断 用户是否登录
@app.before_request
def before_request():
    if request.path == '/login/' or request.path == '/':
        pass
    else:
        username = request.cookies.get('username')
        if not username:
            return redirect('/login')


# 在请求之后运行, 设置响应体为 json
@app.after_request
def after_request(response):
    response.headers["Content-Type"] = "application/json"
    return response


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