zoukankan      html  css  js  c++  java
  • Flask进阶(路由视图,session,蓝图,上下文管理)

    1. 路由+视图
        a. 路由设置的两种方式:
            @app.route('/xxx')
                def index():
                    return "index"

            
            def index():
                return "index"
            app.add_url_rule("/xxx",None,index)
            
            注意事项:
                - 不用让endpoint重名
                - 如果重名函数也一定要相同。
        b. 参数
            rule,                       URL规则
            view_func,                  视图函数名称
            endpoint=None,              名称,用于反向生成URL,即: url_for('名称')
            methods=None,               允许的请求方式,如:["GET","POST"]
            strict_slashes=None,        对URL最后的 / 符号是否严格要求,
            redirect_to=None,           重定向到指定地址

            defaults=None,              默认值,当URL中无参数,函数需要参数时,使用defaults={'k':'v'}为函数提供参数
            subdomain=None,             子域名访问
        c. CBV
            import functools
            from flask import Flask,views
            app = Flask(__name__)


            def wrapper(func):
                @functools.wraps(func)
                def inner(*args,**kwargs):
                    return func(*args,**kwargs)

                return inner



            class UserView(views.MethodView):
                methods = ['GET']
                decorators = [wrapper,]

                def get(self,*args,**kwargs):
                    return 'GET'

                def post(self,*args,**kwargs):
                    return 'POST'

            app.add_url_rule('/user',None,UserView.as_view('uuuu'))

            if __name__ == '__main__':
                app.run()
        d. 自定义正则
            from flask import Flask,url_for

            app = Flask(__name__)

            # 步骤一:定制类
            from werkzeug.routing import BaseConverter
            class RegexConverter(BaseConverter):
                """
                自定义URL匹配正则表达式
                """

                def __init__(self, map, regex):
                    super(RegexConverter, self).__init__(map)
                    self.regex = regex

                def to_python(self, value):
                    """
                    路由匹配时,匹配成功后传递给视图函数中参数的值
                    :param value:
                    :return:
                    """
                    return int(value)

                def to_url(self, value):
                    """
                    使用url_for反向生成URL时,传递的参数经过该方法处理,返回的值用于生成URL中的参数
                    :param value:
                    :return:
                    """
                    val = super(RegexConverter, self).to_url(value)
                    return val

            # 步骤二:添加到转换器
            app.url_map.converters['reg'] = RegexConverter

            """
            1. 用户发送请求
            2. flask内部进行正则匹配
            3. 调用to_python(正则匹配的结果)方法
            4. to_python方法的返回值会交给视图函数的参数

            """

            # 步骤三:使用自定义正则
            @app.route('/index/<reg("d+"):nid>')
            def index(nid):
                print(nid,type(nid))

                print(url_for('index',nid=987))
                return "index"

            if __name__ == '__main__':
                app.run()
        
    2. session实现原理(源码)
        - 请求到来之后wsgi会触发__call__方法,由__call__方法再次调用wsgi_app方法
            - 在wsgi_app方法中:
                - 首先将 请求相关+空session 封装到一个RequestContext对象中,即:ctx。
                - 将ctx交给LocalStack对象,再由LocalStack将ctx添加到Local中,Local结构:
                    __storage__ = {
                        1231:{stack:[ctx,] }
                    }
                - 根据请求中的cookie中提取名称为sessionid对应的值,对cookie进行加密+反序列化,再次赋值给ctx中的session
                
                -> 视图函数
                
                - 把session中的数据再次写入到cookie中。
                - 将ctx删除
            - 结果返回给用户浏览器
            - 断开socket连接
        
    3. 蓝图
        目标:给开发者提供目录结构
        
        其他:
            - 自定义模板、静态文件
            - 某一类url添加前缀
            - 给一类url添加before_request
        
    4. threading.local【和flask无任何关系】
        作用:为每个线程创建一个独立的空间,使得线程对自己的空间中的数据进行操作(数据隔离)。
            import threading
            from threading import local
            import time

            obj = local()


            def task(i):
                obj.xxxxx = i
                time.sleep(2)
                print(obj.xxxxx,i)

            for i in range(10):
                t = threading.Thread(target=task,args=(i,))
                t.start()

        问题:
            - 如何获取一个线程的唯一标记? threading.get_ident()
            - 根据字典自定义一个类似于threading.local功能?
                import time
                import threading

                DIC = {}

                def task(i):
                    ident = threading.get_ident()
                    if ident in DIC:
                        DIC[ident]['xxxxx'] = i
                    else:
                        DIC[ident] = {'xxxxx':i }
                    time.sleep(2)

                    print(DIC[ident]['xxxxx'],i)

                for i in range(10):
                    t = threading.Thread(target=task,args=(i,))
                    t.start()
                
            - 根据字典自定义一个为每个协程开辟空间进行存取数据。
            
                import time
                import threading
                import greenlet

                DIC = {}

                def task(i):
                    
                    # ident = threading.get_ident()
                    ident = greenlet.getcurrent()
                    if ident in DIC:
                        DIC[ident]['xxxxx'] = i
                    else:
                        DIC[ident] = {'xxxxx':i }
                    time.sleep(2)

                    print(DIC[ident]['xxxxx'],i)

                for i in range(10):
                    t = threading.Thread(target=task,args=(i,))
                    t.start()
            
            - 通过getattr/setattr 构造出来 threading.local的加强版(协程)
                import time
                import threading
                try:
                    import greenlet
                    get_ident =  greenlet.getcurrent
                except Exception as e:
                    get_ident = threading.get_ident

                class Local(object):
                    DIC = {}

                    def __getattr__(self, item):
                        ident = get_ident()
                        if ident in self.DIC:
                            return self.DIC[ident].get(item)
                        return None

                    def __setattr__(self, key, value):
                        ident = get_ident()
                        if ident in self.DIC:
                            self.DIC[ident][key] = value
                        else:
                            self.DIC[ident] = {key:value}
                        

                obj = Local()

                def task(i):
                    obj.xxxxx = i
                    time.sleep(2)
                    print(obj.xxxxx,i)

                for i in range(10):
                    t = threading.Thread(target=task,args=(i,))
                    t.start()
            
    5. 上下文管理(第一次)
        请求到来时候:
            # ctx = RequestContext(self, environ) # self是app对象,environ请求相关的原始数据
            # ctx.request = Request(environ)
            # ctx.session = None
            
            # 将包含了request/session的ctx对象放到“空调”
                {
                    1232:{ctx:ctx对象}
                    1231:{ctx:ctx对象}
                    1211:{ctx:ctx对象}
                    1111:{ctx:ctx对象}
                    1261:{ctx:ctx对象}
                }
                
        视图函数:
            from flask import reuqest,session
            
            request.method
            
            
        请求结束:
            根据当前线程的唯一标记,将“空调”上的数据移除。

    6 flask-session
        
            pip3 install flask-session
            
            掌握:
                - 使用
                    # by luffycity.com
                    import redis
                    from flask import Flask,request,session
                    from flask.sessions import SecureCookieSessionInterface
                    from flask_session import Session

                    app = Flask(__name__)

                    # app.session_interface = SecureCookieSessionInterface()
                    # app.session_interface = RedisSessionInterface()
                    app.config['SESSION_TYPE'] = 'redis'
                    app.config['SESSION_REDIS'] = redis.Redis(host='140.143.227.206',port=6379,password='1234')
                    Session(app)

                    @app.route('/login')
                    def login():
                        session['user'] = 'alex'
                        return 'asdfasfd'

                    @app.route('/home')
                    def index():
                        print(session.get('user'))

                        return '...'


                    if __name__ == '__main__':
                        app.run()
                - 原理:
                    - session数据保存到redis
                        session:随机字符串1:q23asifaksdfkajsdfasdf
                        session:随机字符串2:q23asifaksdfkajsdfasdf
                        session:随机字符串3:q23asifaksdfkajsdfasdf
                        session:随机字符串4:q23asifaksdfkajsdfasdf
                        session:随机字符串5:q23asifaksdfkajsdfasdf
                    - 随机字符串返回给用户。
                        随机字符串
                    
                    
                    源码:
                        from flask_session import RedisSessionInterface

  • 相关阅读:
    设置多台机器linux服务器ssh相互无密码访问
    linux环境下 卸载 Oracle11G
    树型结构递归 实体递归 JSON格式
    Fiddler工具非常强大好用
    SQL 分页 SQL SERVER 2008
    Html table 细边框
    Oracle用户密码过期的处理方法
    将目录下面所有的 .cs 文件合并到一个 code.cs 文件中,写著作权复制代码时的必备良药
    微软帮你做了枚举的位运算
    根据身份证算出生日期和性别
  • 原文地址:https://www.cnblogs.com/l-jie-n/p/10089388.html
Copyright © 2011-2022 走看看