欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Flask中before_request与after_request使用

程序员文章站 2022-05-04 12:28:18
[TOC] 如果有一天公司业务需求需要给所有视图函数添加功能,可以通过装饰器实现,但视图函数太多,有没有更好的办法呢? before_request与after_request很简单,实现中功能同Django中中间件process_request与process_response的功能相同 1.前提 ......

[toc] 如果有一天公司业务需求需要给所有视图函数添加功能,可以通过装饰器实现,但视图函数太多,有没有更好的办法呢?

before_request与after_request很简单,实现中功能同django中中间件process_request与process_response的功能相同

1.前提,装饰器的弊端

我们现在有一个 flask 程序其中有3个路由和视图函数,如下:

from flask import flask

app = flask(__name__)  # type:flask


@app.route("/login")
def login():
    return "login"

@app.route("/index")
def index():
    return "index"

@app.route("/home")
def home():
    return "login"

app.run("0.0.0.0", 5000)
from flask import flask

app = flask(__name__)  # type:flask


@app.route("/login")
def login():
    return "login"

@app.route("/index")
def index():
    return "index"

@app.route("/home")
def home():
    return "login"

app.run("0.0.0.0", 5000)

如果登陆了,就可以访问 index 和 home 页面,如果没登录就跳转到 login 登录

要怎么解决呢, session 对, 用 session 除了 login 函数之外的所有函数里面全校验 session 是否登录了

太麻烦了,现在咱们只有3个函数,如果成百上千个怎么整啊

装饰器,对没错,装饰器是一个很好的方案,但是啊,我现在还是成败上千个函数,我要在每一个函数定义的时候加上@装饰器,还是很麻烦

2.before_request与after_request

2.1 before_request分析:

from flask import flask, render_template

app = flask(__name__)

@app.route("/home")
def home():
    return "hello"

@app.before_request
def be1():
    print("be1")
    return "出错了"
    # return none

@app.before_request
def be2():
    print("be2")
    return none

@app.after_request
def af1(res):
    print("af1")
    return res

@app.after_request
def af2(res):
    print("af2")
    return res


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

报错信息:

# django中,如果当请求到达请求1的时候直接不符合条件返回,即return httpresponse("md1中断"),程序将把请求直接发给中间件1返回,然后依次返回到请求者,不再执行视图函数
# 在flask中,如果当请求到达请求1的时候直接不符合条件返回,则会中最后一个@app.after_request中依次返回到请求者,不再执行视图函数,结果如下:
返回md2中断的页面,后台打印如下:
be1
af2
af1

2.2 after_request分析:

@app.after_request报错则会依次返回结果  

from flask import flask, render_template

app = flask(__name__)

@app.route("/home")
def home():
    return "hello"

@app.before_request
def be1():
    print("be1")
    # return "出错了"
    return none

@app.before_request
def be2():
    print("be2")
    return none

@app.after_request
def af1(res):
    print("af1")
    return res

@app.after_request
def af2(res):
    print("af2")
    # return res
    return "出错了"

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

报错信息:

# 返回结果be1
be2
af2
af1

3.before_request应用

@app.before_request 在请求(request)进入视图函数之前执行

@app.before_request 也是一个装饰器,他所装饰的函数,都会在请求进入视图函数之前执行

request.path 是来读取当前的url地址如果是 /login 就允许直接通过 return none 你可以理解成通过放行

校验session中是否有user 如果没有的话,证明没有登录,所以毫不留情的 redirect("/login") 跳转登录页面

还有一个要提的 @app.before_first_request 它与 @app.before_request 极为相似或者说是一模一样,只不过它只会被执行一次

from flask import flask
from flask import request
from flask import redirect
from flask import session

app = flask(__name__)  # type:flask
app.secret_key = "dragonfire"

@app.before_request
def is_login():   #白名单
    if request.path == "/login":
        return none
   #验证session
    if not session.get("user"):
        return redirect("/login")  return none

@app.route("/login")
def login():
    return "login"

@app.route("/index")
def index():
    return "index"

@app.route("/home")
def home():
    return "login"

app.run("0.0.0.0", 5000)

4.before_request应用

@app.after_request 在响应(response)返回客户端之前执行 , 结束视图函数之后

@app.after_request必须return返回上一层的参数environ,否则会报错

@app.after_request
def foot_log(environ):
    if request.path != "/login":
        print("有客人访问了",request.path)
    return environ

5.用flask的实现一个简单的页面登录

基于before_request与after_request的验证登录

from flask import flask,render_template,request,redirect,session
app = flask(__name__,template_folder='templates')
app.secret_key = "sdsfdsgdfgdfgfh"

@app.before_request
def process_request():
    if request.path=="/login":
        return none
    if not session.get("user_info"):
        return redirect("/login")
    return none
@app.after_request
def process_response(response):
    print(2222)
    return response

@app.route("/login",methods=["get","post"])
def login():
    if request.method=="get":
        return render_template("login.html")
    else:
        # print(request.values)   #这个里面什么都有,相当于body
        username = request.form.get("username")
        password = request.form.get("password")
        if username=="annie" and password=="123":
            session["user_info"] = username
            # session.pop("user_info")  #删除session
            return redirect("/index")
        else:
            # return render_template("login.html",**{"msg":"用户名或密码错误"})
            return render_template("login.html",msg="用户名或者密码错误")


@app.route("/index",methods=["get","post"])
def index():
    # if not session.get("user_info"):
    #     return redirect("/login")
    return render_template("index.html")


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