• 第二篇 Flask基础篇之(闪现,蓝图,请求扩展,中间件)


     

    本篇主要内容:

      闪现

      请求扩展  

      中间件  

      蓝图

    写装饰器,常用 functools模块,帮助设置函数的元信息

    复制代码
    import functools
    
    def wrapper(func):
        @functools.wraps(func)
        def inner(*args,**kwargs):
            return func(*args,**kwargs)
    
        return inner
    
    @wrapper
    def f1():
        pass
    
    print(f1.__name__)  # f1
    复制代码

    续接第一篇

    8.Flask之闪现

    复制代码
    # 首先要导入flash 和 get_flashed_messages
    from flask import Flask,flash,get_flashed_messages
    app = Flask(__name__)
    app.secret_key="1234"
    
    @app.route("/get")
    def get():
        # 2.从某个地方获取设置过的所有值,并清除。 类似于pop
        # 第一次运行可以获取到所有的设置的值;第二次运行就清除掉了所有的设置的值
        data = get_flashed_messages()
        print(data)
        return "hello World"
    
    @app.route("/set")
    def set():
        # 1. 向某个地方设置一个值
        flash("军人")
        return "Hello army"
    
    if __name__=="__main__":
        app.run()
    复制代码

    闪现有什么作用呢?

    比如:假设在A页面做个操作,但该操作失败了,要跳转到B页面并显示这些错误信息
    复制代码
    from flask import Flask,flash,get_flashed_messages,request,redirect
    app = Flask(__name__)
    app.debug = True
    app.secret_key="1234"
    
    @app.route("/index")
    def index():
        # get请求用request.args.get, v是接受参数的变量
        # 浏览器请求:
        val = request.args.get('v')
        if val =="body":
            return "hello World, guys"
        # 如果请求参数不是body,则跳转到错误页面,需要将错误信息flash,也就是设置错误值到某个地方
        # A.flash不分类,直接设置值
        flash("前端输入参数错误")
        # B.flash还可以对错误信息,进行分类
        flash("前端输入参数错误", category="x1")
        return redirect("/error")
    
    @app.route("/error")
    def error():
        '''
        显示错误信息
        '''
        # 跳转到error页面后,请求时获取错误信息
        # A.flash没有分类时
        # data = get_flashed_messages()   # 获取的就是flash的值
        # B. 对于有分类的,取值时可以通过 category_filter 根据分类取错误信息
        data = get_flashed_messages(category_filter=['x1'])
        # 可能有很多的错误信息,也可以按照索引的方式取出错误值
        if data:
            msg = data[0]
        else:
            msg = "..."
        return "错误信息:%s" %(msg)
    
    if __name__=="__main__":
        app.run()
    复制代码

    闪现是怎么实现的呢?

    其实,它就是通过session做的,先把数据存在session里,数据如果在session里,只要不删,就永远在。

    然后,如果值被拿走,就会通过session.pop()的方式给拿走。

    所以,就不用担心数据错乱。因为每个用户都会有自己的一个session,基于session就会把数据隔离开了。

    闪现的应用:

      对临时数据操作,如:显示错误信息

    9.Flask之请求扩展(类似Django中间件)--其实也是Flask的中间件

    场景:

    商业应用一般都要求登录后才可以进行其他操作,上一篇我们基于装饰器的方式做,但是如果函数越来越多,那就要新增一个函数,就要添加一个装饰器。

    为了省事,在Django里通过中间件的方式做的,但是Flask里没有类似的中间件,就需要通过Flask里的请求扩展的方式做。

    (1)做用户登录认证 before_request   —常用

    示例:基于Flask的请求扩展做一个用户认证功能

    复制代码
    from flask import Flask,render_template,request,redirect,session,url_for
    
    app = Flask(__name__)
    app.debug = True
    app.secret_key = "123#234"
    
    USERS = {
        1:{"name":"老大", "age":19,"gender":"男", "resume":"言语措辞间都能体会到今日头条的谨小慎微,生怕再出现任何问题……."},
        2:{"name":"老二", "age":18,"gender":"女", "resume":"当打开这款APP之后,就会发现这跟已经“死”去的内涵段子简直是一模一样。更厉害的地方是,它还支持用用户迁移内涵段子上的内容信息。"},
        3:{"name":"老三", "age":17,"gender":"男", "resume":"如果狒狒会说人话,他肯定是在说:喂…你怎么只给我吃了一口就跑了呀,我还没吃饱啊…喂喂喂…给我回来呀!哈哈哈"},
    }
    
    # 基于flask里请求扩展来做
    @app.before_request
    def process_request(*args, **kwargs):
        # 验证表示,任何地址请求都会先执行before_request,所以登录验证就可以在before_request里做用户认证功能了
        print("其他请求之前就执行了process_request")
        # 4.访问/login的时候还没有登录,就会一直重定向到登录页,所以就要设置个白名单,如果请求地址是/login,就返回None
        if request.path == "/login":
            return None
        # 1.登录验证功能
        user = session.get('user_info')
        # 2.如果登录信息正常,什么都不做,程序继续其他执行
        if user:
            return None
        # 3.如果登录验证不通过,就重定向到登录页面
        return redirect("/login")
    
    @app.route("/detail/<int:nid>", methods=['GET'])
    def detail(nid):
        detail_info = USERS.get(nid)
        # 如果有值,就跳到详情页
        return render_template("detail.html",info = detail_info)
    
    @app.route("/index", methods=['GET'])
    def index():
        return render_template("index.html", user_dict=USERS)
    
    @app.route("/login", methods=['GET', 'POST'], endpoint='l1')
    def login():
        if request.method =="GET":
            return render_template("login.html")
        else:
            user = request.form.get("username")
            pwd = request.form.get("password")
            if user == "alex" and pwd =="123456":
                session['user_info'] = user
                return redirect("/index")
            return render_template("login.html", **{"error":"用户名和密码错误"})
    
    if __name__ == "__main__":
        app.run()
    复制代码

    (2)有before_request, 就天然的有after_request —常用

    复制代码
    from flask import Flask,render_template,request,redirect,session,url_for
    app = Flask(__name__)
    app.debug = True
    app.secret_key = 'siuljskdjfs'
    
    @app.before_request
    def process_request1(*args,**kwargs):
        print('process_request1 进来了')
    
    @app.after_request
    def process_response1(response):
        print('process_response1 走了')
        # after_request 必须返回 response
        return response
    
    # 视图函数
    @app.route('/index',methods=['GET'])
    def index():
        print('index函数')
        return "Index"
    
    if __name__ == '__main__':
        app.run()
    复制代码

    (3)请求扩展可以添加多个

    复制代码
    from flask import Flask,render_template,request,redirect,session,url_for
    app = Flask(__name__)
    app.debug = True
    app.secret_key = 'siuljskdjfs'
    
    @app.before_request
    def process_request1(*args,**kwargs):
        print('process_request1 进来了')
        return "拦截"
    
    @app.before_request
    def process_request2(*args,**kwargs):
        print('process_request2 进来了')
    
    @app.after_request
    def process_response1(response):
        print('process_response1 走了')
        # after_request 必须返回 response
        return response
    
    @app.after_request
    def process_response2(response):
        print('process_response2 走了')
        return response
    
    # 视图函数
    @app.route('/index',methods=['GET'])
    def index():
        print('index函数')
        return "Index"
    
    
    if __name__ == '__main__':
        app.run()
    
    '''
    Flask请求扩展也可以写多个
    但是要注意,多个请求扩展的执行顺序是有差别的:
    对于before_request,是按照写的代码的顺序从上到下的顺序正序执行的
    对于after_request, 是按照写的代码的顺序从下到上的顺序倒序执行的
    
    如果before_request return了(即程序被拦截了),其他before_request就不执行了,但是所有的after_request都会继续执行
    '''
    复制代码

     (4)定制错误信息:errorhandler(404)

    复制代码
    from flask import Flask,render_template,request,redirect,session,url_for
    app = Flask(__name__)
    app.debug = True
    app.secret_key = 'siuljskdjfs'
    
    # 经常会出现url不存在的情况,一般会有错误信息
    # 而这个错误信息也是可以进行定制的,根据错误码定制错误信息方法如下:
    @app.errorhandler(404)
    def error_404(arg):
        return "404错误了"
    
    # 视图函数
    @app.route('/index',methods=['GET'])
    def index():
        print('index函数')
        return "Index"
    
    if __name__ == '__main__':
        app.run()

    复制代码

    (5)模板中定制方法(定制模板方法): template_global()  和  template_filter()

    复制代码
    from flask import Flask,request
    app = Flask(__name__)
    app.debug = True
    
    # 这就是基于请求扩展的 定制模板方法
    # 相对于在模板里定制了一个函数
    @app.template_global() def sb(a1, a2): return a1 + a2 if __name__ == '__main__': app.run() #在HTML里调用的方式如下: {{sb(1,2)}}
    复制代码
    复制代码
    from flask import Flask,request
    app = Flask(__name__)
    app.debug = True
    
    # 这就是基于请求扩展的 定制模板方法
    @app.template_filter()
    def db(a1, a2, a3):
        return a1 + a2 + a3
    
    if __name__ == '__main__':
        app.run()
    
    #在HTML里调用的方式如下:
     {{ 1|db(2,3)}   # 参数 a1 = 1,是第一个参数; a2=2 是第二个参数;   a3=3 是第三个参数
    复制代码

    (6)只有第一次请求才执行的:before_first_request

      比如:数据库的连接,初始化操作

    复制代码
    from flask import Flask,request
    app = Flask(__name__)
    app.debug = True
    
    # 内部其实就有个判断,初始值是FALSE,第一次执行后将值改变为True,以后判断后就不执行了
    @app.before_first_request
    def before_first_request2():
        print('before_first_request2')
    
    if __name__ == '__main__':
        app.run()
    复制代码

    10. 中间件

    前面关于请求的中间件已经在请求扩展里讲了。

    由于知道请求之前会执行一个wsgi_app,所以这里做个请求之前的定制,先了解一下

    复制代码
    from flask import Flask
    app = Flask(__name__)
    
    @app.route("/login", methods=['GET', 'POST'])
    def index():
        pass
    
    class Md(object):
        def __init__(self, old_wsgi_app):
            self.old_wsgi_app = old_wsgi_app
    
        def __call__(self, environ, start_response):
            print("开始之前")
            ret = self.old_wsgi_app(environ, start_response)
            print("结束之后")
            return ret
    
    if __name__ =="__main__":
        app.wsgi_app = Md(app.wsgi_app) # 相当于把wsgi_app给更新了
        app.run()
    复制代码

    11.蓝图

    前置情景:一个项目一般会有多个.py文件组成,这些.py文件分别执行不同的功能,那就可以为这些不同功能的.py文件给划分到不同的目录里去。

    所以蓝图用于为应用提供目录划分:

    未使用蓝图的目录结构,但是没有Flask提供的蓝图好,蓝图里还提供了一些类似请求扩展的东西等等。

    使用蓝图的目录结构

               

    使用蓝图的目标:

    1. 构造程序目录

    2. 自定义程序目录

      批量处理url

      定制模板路径和静态文件路径

       请求扩展:

        - 可以针对app, 即全部程序都生效

        - 也可以针对单个的蓝图,即只有在执行该蓝图时,请求扩展才会生效

    Flask的官方文档可知,蓝图需要掌握的几个方面知识点如下:

    1. 注册蓝图

    2. 蓝图资源

    3. 静态文件

    4. 模板

    5. 构造URL

  • 相关阅读:
    Linux中后台执行scp
    无意中发现一个开源的flv播放器
    Spark Label 可以显示多行,但 MX Label 不可以。
    牛到家的Flex效果
    回去研究一下rawChild
    这几天在做图片滤镜
    黑白图片滤镜
    Flash CS3里的滤镜在窗品>属性里,默认是不显示的,你点了后会出现在属性控制面板里
    currentFrameLabel和currentLabel的区别在于flash player9和10
    Flash游戏做html网页做不了的事
  • 原文地址:https://www.cnblogs.com/fengff/p/12426871.html
Copyright © 2020-2023  润新知