zoukankan      html  css  js  c++  java
  • flask框架(七)——蓝图、请求上下文、g对象、信号、flask_session

    蓝图

    作用:对程序进行目录结构划分

    不使用蓝图情况下,自己分文件

    目录结构:

    -templates
    -views
        -__init__.py
        -user.py
        -order.py
    -app.py

    app.py

    from views import app
    if __name__ == '__main__':
        app.run()

    __init__.py

    from flask import Flask,request
    app = Flask(__name__)
    #不导入这个不行
    from . import account
    from . import order
    from . import user

    user.py

    from . import app
    @app.route('/user')
    def user():
        return 'user'

    order.py

    from . import app
    @app.route('/order')
    def order():
        return 'order'

    使用蓝图  (Blueprint)

    目录结构:

    -app01
        -pro
            -templates
            -__init__.py
            -views
        -manage.py

    manage.py

    from  pro import app
    
    if __name__ == '__main__':
        app.run()

    __init__.py

    from flask import Flask
    app=Flask(__name__)
    from pro import views
    app.register_blueprint(views.us)

    views.py

    from flask import Blueprint,render_template
    us=Blueprint("user",__name__)
    @us.route("/")
    def index():
        return render_template("index.html")

    总结:

    1 xxx = Blueprint('account', name,url_prefix='/xxx') :蓝图URL前缀,表示url的前缀,在该蓝图下所有url都加前缀

    2 xxx = Blueprint('account', name,url_prefix='/xxx',template_folder='tpls'):给当前蓝图单独使用templates,向上查找,当前找不到,会找总templates

    3 蓝图的befort_request,对当前蓝图有效

    4 大型项目,可以模拟出类似于django中app的概念

    请求上下文源码分析

    第一阶段:将ctx(request,session)放到Local对象上
                       
    第二阶段:视图函数导入:request/session 
    request.method
        -LocalProxy对象.method,执行getattr方法,getattr(self._get_current_object(), name)
            -self._get_current_object()返回return self.__local(),self.__local(),在LocakProxy实例化的时候,object.__setattr__(self, '_LocalProxy__local', local),此处local就是:partial(_lookup_req_object, 'request')
    
        -def _lookup_req_object(name):
                top = _request_ctx_stack.top #_request_ctx_stack 就是LocalStack()对象,top方法把ctx取出来
                if top is None:
                    raise RuntimeError(_request_ctx_err_msg)
                return getattr(top, name)#获取ctx中的request或session对象
    
    第三阶段:请求处理完毕
            - 获取session并保存到cookie
            - 将ctx删除

    程序运行,两个LocalStack()对象,一个里面放request和session,另一个放g和current_app

    g对象

    专门用来存储用户信息的g对象,g的全称的为global

    g对象的特性:

    当前请求内你设置就可以取,必须先设置,后取,当前请求可以取无限次。就算你在当前请求设置了g对象,如果不取,其他的请求也取不到。

    g对象和session的区别

    session对象是可以跨request的,只要session还未失效,不同的request的请求会获取到同一个session,但是g对象不是,g对象不需要管过期时间,请求一次就g对象就改变了一次,或者重新赋值了一次

    代码示例

    from  flask import Flask,g,redirect
    
    app=Flask(__name__)
    
    def set_g():
        g.name='sb'   #设置g(可以单独这样设置,也可以在视图函数内设置,直接g.属性名设置)
    
    @app.route("/")
    def index():
        set_g()
        return redirect("/index")
    
    @app.route("/index")
    def login():
        print(g.name)   #获取g对象
        return "2"
    
    if __name__ == '__main__':
        app.run()

    信号

    Flask框架中的信号基于blinker,其主要就是让开发者可是在flask请求过程中定制一些用户行为

    安装:pip install blinker

    内置信号:

    request_started = _signals.signal('request-started')                # 请求到来前执行
    request_finished = _signals.signal('request-finished')              # 请求结束后执行
     
    before_render_template = _signals.signal('before-render-template')  # 模板渲染前执行
    template_rendered = _signals.signal('template-rendered')            # 模板渲染后执行
     
    got_request_exception = _signals.signal('got-request-exception')    # 请求执行出现异常时执行
     
    request_tearing_down = _signals.signal('request-tearing-down')      # 请求执行完毕后自动执行(无论成功与否)
    appcontext_tearing_down = _signals.signal('appcontext-tearing-down')# 应用上下文执行完毕后自动执行(无论成功与否)
     
    appcontext_pushed = _signals.signal('appcontext-pushed')            # 应用上下文push时执行
    appcontext_popped = _signals.signal('appcontext-popped')            # 应用上下文pop时执行
    message_flashed = _signals.signal('message-flashed')                # 调用flask在其中添加数据时,自动触发

    使用信号:

    from flask import Flask,signals
    
    app = Flask(__name__)
    #给信号绑定要执行的函数
    #无需管调用,因为flask,已经给我们设置调用点
    def func(*args,**kwargs):
        print('触发型号',args,kwargs)
    #与该信号进行绑定
    signals.request_started.connect(func)     #绑定信号,请求到来前就会执行绑定的函数
    # 触发信号: signals.request_started.send()
    @app.before_first_request
    def before_first1(*args,**kwargs):
        print("befor_first_request")
    
    @app.before_request
    def before_first3(*args,**kwargs):
        print("befor_request")
    
    @app.route('/',methods=['GET',"POST"])
    def index():
        print('视图')
        return "视图"

     一个信号触发点的流程:(了解知识点)

    a. before_first_request
    b. 触发 request_started 信号
    c. before_request
    d. 模板渲染
        渲染前的信号 before_render_template.send(app, template=template, context=context)
            rv = template.render(context) # 模板渲染
        渲染后的信号 template_rendered.send(app, template=template, context=context)
    e. after_request
    f. session.save_session()
    g. 触发 request_finished信号        
        如果上述过程出错:
            触发错误处理信号 got_request_exception.send(self, exception=e)
                
    h. 触发信号 request_tearing_down

    自定义信号(了解)

    from flask import Flask
    from flask.signals import _signals
    
    app = Flask(import_name=__name__)
    
    # 自定义信号
    xxxxx = _signals.signal('xxxxx')
    
    def func(sender,a):
        print(sender,a)
        print("我是自定义信号")
    
    # 自定义信号中注册函数
    xxxxx.connect(func)
    
    @app.route("/x")
    def index():
        # 触发信号
        xxxxx.send("sb",a="1")   #最少传递一个参数
        return 'Index'
    
    if __name__ == '__main__':
        app.run()

     flask-session

    作用:将默认保存的签名cookie中的值 保存到 redis/memcached/file/Mongodb/SQLAlchemy

    安装:pip3 install flask-session

    使用1  (复杂的方式)

    from flask import Flask,session
    from flask_session import RedisSessionInterface
    import redis
    app = Flask(__name__)
    app.secret_key="ajksda"
    conn=redis.Redis(host='127.0.0.1',port=6379)
    #use_signer设置是否需要secret_key签名,permanent设置关闭浏览器cookie是否失效
    app.session_interface=RedisSessionInterface(conn,key_prefix='jason',use_signer=True, permanent=False)
    @app.route('/')
    def hello_world():
        session['sb']='jason'
        return 'Hello World!'
    
    @app.route("/index")
    def index():
        print(session['sb'])
        return "ok"
    
    if __name__ == '__main__':
        app.run()

    使用2 (简单的方式)

    from flask import Flask,session
    import  redis
    from flask_session import Session
    app = Flask(__name__)
    app.config['SESSION_TYPE'] = 'redis'
    app.config['SESSION_REDIS'] =redis.Redis(host='127.0.0.1',port='6379')
    app.config['SESSION_KEY_PREFIX']="jason"
    Session(app)
    
    @app.route('/')
    def hello_world():
        session['sb']='jason'
        return 'Hello World!'
    
    @app.route("/index")
    def index():
        print(session['sb'])
        return "ok"
    
    if __name__ == '__main__':
        app.run()
  • 相关阅读:
    AS3 判断双击事件
    php 数据类型转换与比较
    几行几列算法
    CCNode的属性说明
    bitmapdata的知识点
    addFrameScript用法
    TweenMax.allTo
    flash TweenMax用法
    flash流媒体资料
    c实现windows socket
  • 原文地址:https://www.cnblogs.com/wangcuican/p/11852441.html
Copyright © 2011-2022 走看看