zoukankan      html  css  js  c++  java
  • DAY 215 Flask中before_request与after_request使用

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

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

    一、前提,装饰器的弊端

      我们现在有一个 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)

    复制代码

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

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

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

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

    二、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

    三、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)
    复制代码

    四、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

    五、用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)
    复制代码
    https://www.cnblogs.com/WiseAdministrator/
  • 相关阅读:
    微信——获取用户基本信息及openid 、access_token、code
    Java中的标记接口(zz)
    深入理解Java的注解(Annotation):注解处理器(3)
    深入理解Java的注解(Annotation):自定义注解入门(2)
    深入理解Java的注解(Annotation):基本概念(1)
    TCP 粘包及其解决方案(zz)
    TCP,UDP,IP包头格式及说明(zz)
    python 如何将JSON数据原封不动的转为字符串(顺序不能变动)?
    mysql:functional dependency
    什么是“几何级数”?什么是“算数级数”?有啥区别?
  • 原文地址:https://www.cnblogs.com/DEJAVU888/p/15562443.html
Copyright © 2011-2022 走看看