zoukankan      html  css  js  c++  java
  • Flask基础(3):session、flash、特殊装饰器、蓝图、路由正则匹配、上下文管理 & flask-session

    Session:

    Flask 默认将 session 以加密的形式放到了浏览器的 cookie 中 
    Flask 的 session 就是一个字典,字典有什么方法 session 就有什么方法
    flask session 原理:当请求刚进来时,flask会读取cookie中 session(配置文件中能改这个名称) 对应的值,将这个值解密并反序列化成为一个字典放入内存,
                        以便视图函数使用;
                        在视图函数中使用时,按照字典的方法使用;
                        当请求结束时,flask会读取内存中字典的值,进行序列化+加密,然后再写入到用户的 cookie 中

    flash:

    # flash 是 取一次就没有;基于 session 实现的
    # 原理:在 session 中存储一个数据,读取时通过 pop 将数据移除,从而达到只能取一次的效果
    from flash import get_flashed_messages
    flash("临时数据存储","error")  # 存 flash;"error" 表示分类
    get_flashed_messages()   # 取 flash 中的值;列表的形式; get_flashed_messages(category_filter=["error"]) 表示根据 分类取 flash

    特殊装饰器:(重点)

      **1. @app.before_request  # 所有请求之前进行的操作;被装饰的函数没有 参数 和 返回值;作用类似于 Django 的 process_request
        2. @app.template_global()  # 给模板用的
        3. @app.template_filter()  # 给模板用的
        
      **4. @app.after_request  # 被装饰的函数要有 参数 和 返回值;作用类似于 Django 的 process_response
            
            @app.after_request
            def test(response):
                print("after_request")
                return response
        # 对于有多个 @app.before_request ,谁先定义谁先执行;对于有多个 @app.after_request ,谁先定义谁后执行;类似于 Django 中间件的执行顺序
        
        # 对于 before_request,可以在定义自己逻辑时添加返回值,这样就不会执行后面的 before_request 和 视图,但还会执行所有的 after_request;这是和 Django(1.10以后版本不一样的地方)
        
        5. @app.before_first_request  # 只有第一次请求才执行
        6. @app.errorhandler(错误码)  # 报错的时候执行的函数;可用于定制错误信息(页面)
            
            @app.errorhandler(404)
            def not_found(arg): # arg 是错误信息
                print(arg)  
                return "没找到"

    Blueprint:蓝图

    示例目录:

    crm
    |---crm
        |--- __init__.py  # 实例化 Flask 等等
        |---views
            |---account.py
            |---user.py
    |---manage.py  # 入口函数

    manage.py

    from crm import create_app
    
    app = create_app()  
    
    if __name__ == '__main__':
        app.run()  # 运行 Flask 的实例

    crm/__init__.py

    from flask import Flask
    from .views.account import ac
    from .views.user import uc
    
    def create_app():
    
        app = Flask(__name__)
    
        # @app.before_request   # 全局性的 before_request
        # def x1():
        #     print('app.before_request')
    
        app.register_blueprint(ac)
        app.register_blueprint(uc,url_prefix='/api')  # 给 uc 这个蓝图的 url 添加一个 前缀
        return app

    crm/views/account.py

    from flask import Blueprint,render_template
    
    ac = Blueprint('ac',__name__)  # 实例化一个蓝图
    
    @ac.before_request  # 只给 ac 这个蓝图添加 before_request
    def x1():
        print('app.before_request')
    
    @ac.route('/login')
    def login():
        return render_template('login.html')
    
    
    @ac.route('/logout')
    def logout():
        return 'Logout'

    crm/views/user.py

    from flask import Blueprint
    
    uc = Blueprint('uc',__name__)
    
    @uc.route('/list')
    def list():
        return 'List'
    
    @uc.route('/detail')
    def detail():
        return 'detail'

    蓝图的作用:

    1. 目录结构的划分
    2. 路径加前缀
    3. 给某些应用(视图)加装饰器

    路由的正则匹配:

    # 1. 先定义一个类: RegexConverter(BaseConverter)
    # 2. app.url_map.converters["reg"] = RegexConverter
    # 3. 用户发送请求
    # 4. 使用自定义正则:
        @app.route("/index/<reg('d+'):nid>")
        def index(nid):
            print(nid,type(nid)
            print(url_for('index',nid=987)  # 返回生成url时,自动触发 RegexConverter 的 to_url 方法
    # 4. flask内部进行正则匹配
    # 5. to_python 方法的返回值会交给视图函数的参数

    上下文管理:

    1. request
    2. session  # 注: Flask 默认将 session 以加密的形式放到了浏览器的 cookie 里面
    3. app
    4. g

    请求--视图--响应 大致流程:

    请求到来时:
        # ctx = RequestContext(self,environ)  # self 是 app对象,environ表示请求相关的原始数据
        # ctx.request = Request(environ)  
        # ctx.session = None
        
        # 将包含了 request和session 的ctx对象打包放到某个地方(相当于一个大字典;根据线程或协程加个唯一标识,放进去的,所以数据相互隔离)
            {
                1232:{ctx:ctx对象},
                ...
            }
    视图函数:
        from flask import request,session
        # 上述代码背后的过程:根据当前线程或者协程的唯一标识,取到 ctx对象,然后取到 request和session
    请求结束:
        根据当前线程的唯一标识,将 大字典 中该线程对应的数据移除

    上下文管理--request:

    # 1. wsgi:初步处理请求
    # 2. __call__ 方法 --> wsgi_app 方法
    # 3. wsgi_app方法:
            ctx = RequestContext(session,request)
            ctx.push()
    # 4. LocalStack:把 ctx 对象添加到 Local 中 (LocalStack起到一个中介的作用:把 Local 中的数据维护成一个栈;视图函数取值时也是来 LocalStack 中取值,而不能直接去 Local 中取)
    # 5. Local:为每个线程或协程开辟一块相互隔离的内存空间; local对象中有一个 __storage__ 的字典
            __storage__ = {
                线程/协程唯一标识:{"stack":[ctx对象(request和session),]}
            }

    上下文管理--session:

    # 通过 LocalStack 获取 ctx 中的 session,给 session 赋值(从 cookie 中读取数据,进行解密和反序列化;调用 open_session() 方法)

    补充:

    # Flask 和 Django 对比:
        相同点:都是基于 wsgi 协议写的
        最大不同点:request的机制不同:请求相关的数据,对于Django是通过参数传递一个一个传递过来的;flask是把请求相关的数据放到“一个地方”(大字典),以后就来这里取对应的数据
    
    # 全局变量只有在初次加载时执行
    # 类中的 __slots__() 的作用:只允许该类的实例添加 __slots__ () 中的属性

    flask-session:

    # Flask 第三方组件--flask-session:可将 session 保存到 redis 中

    安装:

    pip install flask-session  

    使用:

    import redis
    from flask import Flask,request
    from flask_session import Session  # 导入 flask-session 中的 Session
    
    app = Flask(__name__)
    
    app.config["SESSION_TYPE"] = "redis"  # 3. 由下面的分析可知,配置文件中应该要先配置好 SESSION_TYPE; 此时 app.session_interface = RedisSessionInterface();RedisSessionInterface 中也有 open_session 和 save_session 这两个方法
    app.config["SESSION_REDIS"] = redis.Redis(host="127.0.0.1",port=6379,password="")  # 4. 配置 session 的 Redis
    # 通过这些操作, session 就会保存到 redis 中;此时保存在 浏览器中的 cookie 是一个 随机字符串(uuid.uuid4()),当请求到达时 通过这个 cookie(随机字符串)来 redis 中取 session
    
    # 1. flask 默认的 session 处理是通过 app.session_interface = SecureCookieSessionInterface()
    Session(app)
    # 2. app 经过 Session 实例化之后,app.session_interface = self._get_interface(app) ; session 保存到哪和 配置文件中的 "SESSION_TYPE" 有关
    
    pass 
  • 相关阅读:
    python 之 xlrd模块 excel的读使用
    将str文本类型转换为dict
    pycharm快捷键、常用设置、配置管理
    Bye bye bye
    课题一--作业复习
    python 整齐输出与编码读写
    图像分割——并行区域技术
    主动轮廓模型(重点)
    边界技术
    二阶导数算子
  • 原文地址:https://www.cnblogs.com/neozheng/p/10150644.html
Copyright © 2011-2022 走看看