zoukankan      html  css  js  c++  java
  • Flask之路由系统,CBV与FBV,请求响应,模板语言,session使用及原理,闪现,仿中间件之扩展

    一、路由系统

     1. 示例

    from flask import Flask,render_template,request,redirect,session,url_for
    
    app = Flask(__name__)
    
    
    # endpoint别名,通过别名可反向生成url
    # url后跟参数规则/index/<int:nid>,int需要指定,字符串可以直接使用<nid>
    # 参数数据类型示例
    # @app.route('/user/<username>')
    # @app.route('/post/<int:post_id>')
    # @app.route('/post/<float:post_id>')
    # @app.route('/post/<path:path>')
    # @app.route('/login', methods=['GET', 'POST'])
    
    
    @app.route('/index/<int:nid>',methods=['GET',"POST"],endpoint='fff')
    def index(nid):
    v = url_for('fff',nid=123) # 结合endpoint,url_for反向生成url,可传参
    print(v) # /index/123
    return 'xxxx'
    
    
    if __name__ == '__main__':
    app.run()
    

     2. @app.route和app.add_url_rule参数

               rule                                     URL规则
                view_func,                  视图函数名称
                defaults=None,              默认值,在路由装饰器中为视图函数预设的实参,当URL中无参数,视图函数需要参数时,使用defaults={'k':'v'}为视图函数提供参数
                endpoint=None,              名称,用于反向生成URL,即: url_for('名称')
                methods=None,               允许的请求方式,如:["GET","POST"]
                
    
                strict_slashes=None,        对URL最后的 / 符号是否严格要求,
                                            如:
                                                @app.route('/index',strict_slashes=False),
                                                    访问 http://www.xx.com/index/ 或 http://www.xx.com/index均可
                                                @app.route('/index',strict_slashes=True)
                                                    仅访问 http://www.xx.com/index 
    
    
                redirect_to=None,           重定向到指定地址
                                            如:
                                                @app.route('/index/<int:nid>', redirect_to='/home/<nid>')
                                                或
                                                def func(adapter, nid):
                                                    return "/home/888"
                                                @app.route('/index/<int:nid>', redirect_to=func)
    
    
                subdomain=None,             子域名访问,不加subdomain默认为www
                                                    from flask import Flask, views, url_for
    
                                                    app = Flask(import_name=__name__)
                                                    app.config['SERVER_NAME'] = 'wupeiqi.com:5000'
    
    
                                                    @app.route("/", subdomain="admin")
                                                    def static_index():
                                                        """Flask supports static subdomains
                                                        This is available at static.your-domain.tld"""
                                                        return "static.your-domain.tld"
    
    
                                                    @app.route("/dynamic", subdomain="<username>")      # 动态接收子域名,并可传为参数
                                                    def username_index(username):
                                                        """Dynamic subdomains are also supported
                                                        Try going to user1.your-domain.tld/dynamic"""
                                                        return username + ".your-domain.tld"
    
    
                                                    if __name__ == '__main__':
                                                        app.run()
    View Code

    3. flask扩展支持正则

    from flask import Flask,url_for
    from werkzeug.routing import BaseConverter
    app = Flask(__name__)
    
    
    class RegexConverter(BaseConverter):
        """
        flask中的url所有的数据类型得有自己的对应的类
        DEFAULT_CONVERTERS = {
        'default':          UnicodeConverter,
        'string':           UnicodeConverter,
        'any':              AnyConverter,
        'path':             PathConverter,
        'int':              IntegerConverter,
        'float':            FloatConverter,
        'uuid':             UUIDConverter,
        }
        自定义URL匹配正则表达式,RegexConverter类时之拥有正则可以匹配的类,进行匹配操作
        """
    
        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['regex'] = RegexConverter        # 将自定义正则匹配的类加入converters
    
    
    @app.route('/index/<regex("d+"):nid>',methods=['GET',"POST"],endpoint='fff')
    def index(nid):
        v = url_for('fff',nid=nid)
        print(v)                    # 输入:http://127.0.0.1:5000/index/888,输出/index/888
        return 'xxx'
    
    
    if __name__ == '__main__':
        app.run()
    

     二、Flask的FBV与CBV

    1. FBV

    # 方式一
    @app.route('/index/<regex("d+"):nid>',methods=['GET',"POST"],endpoint='fff')
    def index(nid):
        v = url_for('fff',nid=nid)
        print(v)                    # 输入:http://127.0.0.1:5000/index/888,输出/index/888
        return 'xxx'
    
    --------------------------------------------------------------------------------
    # 方式二
    def index(nid):
        v = url_for('fff',nid=nid)
        print(v)                    # 输入:http://127.0.0.1:5000/index/888,输出/index/888
        return 'xxx'
    
    app.add_url_rule('/index',index)
    View Code

    2. CBV

    from flask import Flask,views,url_for
    app = Flask(__name__)
    
    
    def auth(func):
        def wrapper(*args,**kwargs):
            print('before')
            result = func(*args,**kwargs)
            print('after')
            return result
        return wrapper
    
    class IndexView(views.MethodView):
    
        methods = ["GET"]           # 相当于FBV中的@app.route('/index',methods=['GET','POST'])
    
        decorators = [auth,]        # 所有的方法都经过这个装饰器
    
        def get(self):
            v = url_for('fff')      # 配合IndexView.as_view(name='fff')使用
            print(v)
            return "GET"
    
        def post(self):
            return "POST"
    
    app.add_url_rule('/index',view_func=IndexView.as_view(name='fff'),)
    # name='index' 相当于FBV的endpoint使用,可反向生成url
    
    if __name__ == '__main__':
        app.run()
    View Code

     三、请求与相应

    1. 请求及相应相关信息

            # 请求相关信息
            # request.method
            # request.args
            # request.form
            # request.values
            # request.cookies
            # request.headers
            # request.path
            # request.full_path
            # request.script_root
            # request.url
            # request.base_url
            # request.url_root
            # request.host_url
            # request.host
            # request.files
            # obj = request.files['the_file_name']
            # obj.save('/var/www/uploads/' + secure_filename(f.filename))
    
            # 响应相关信息
            # return "字符串"
            # return render_template('html模板路径',**{})
            # return redirect('/index.html')
    
            # response = make_response(render_template('index.html'))
            # response是flask.wrappers.Response类型
            # response.delete_cookie('key')
            # response.set_cookie('key', 'value')
            # response.headers['X-Something'] = 'A value'
            # return response
    View Code

    2. 示例及urlencode,unquote,quote,jsonify,make_response的使用

    from flask import Flask,url_for,request,jsonify,make_response
    from urllib.parse import urlencode,quote,unquote
    
    app = Flask(__name__)
    
    @app.route('/index',endpoint='xxx')
    def index():
        # request
        # get_data = request.args             # http://127.0.0.1:5000/index?nid=1&name=eiyouwei
        # print(get_data)                     # ImmutableMultiDict([('nid', '1'), ('name', 'eiyouwei')])
        #
        # v = request.args.getlist('name')    # http://127.0.0.1:5000/index?nid=1&name=eiyouwei
        # print(v)                            # ['eiyouwei']
        #
        # 使用python模块urlencode,生成url参数
        # get_data = request.args             # http://127.0.0.1:5000/index?nid=1&name=eiyouwei
        # get_dict = get_data.to_dict()       # 将参数信息转化为字典
        # get_dict['gender'] = 'male'
        # url = urlencode(get_dict)
        # print(url)                          # nid=1&name=eiyouwei&gender=male
    
        # 针对中文在url参数中转化为的特殊字符的转化工具unquote,quote
        # val = request.query_string          # http://127.0.0.1:5000/index?nid=1&name=%E5%93%8E%E5%91%80%E5%91%80
        # print(val)                          # b'nid=1&name=%E5%93%8E%E5%91%80%E5%91%80'
        # print(unquote('%E5%93%8E%E5%91%80%E5%91%80'))       # 哎呀呀
        # print(quote('哎呀呀'))                              # %E5%93%8E%E5%91%80%E5%91%80
    
    
    
        # response
        # return jsonify(name='alxe',age='180')
        # '''
        # jsonify返回json格式的数据
        # {
        #   "age": "180",
        #   "name": "alxe"
        # }
        # '''
        response = make_response('xxx')         # make_response可以响应头等加入信息,操作
        response.headers['Olive'] = '111111'    # 给响应头加入了信息Olive:111111
        return response
    
    if __name__ == '__main__':
        app.run()
    

     四、模板语言(jinjia2)

    1. 视图函数

    from flask import Flask,render_template,Markup
    
    app = Flask(__name__)
    
    def test(a1,a2):
        return a1 + a2
    
    @app.template_global()          # 无需传参,jinjia2全局可使用
    def sb(a1, a2):
        return a1 + a2
    
    
    @app.template_filter()          # jinjia2简单操作即可使用
    def db(a1, a2, a3):
        return a1 + a2 + a3
    
    
    @app.route('/index',endpoint='xxx')
    def index():
        v1 = '字符串'
        v2 = [11,22,33]
        v3 = {'k1':'v1','k2':'v2'}
        # v4 = "<input type='text'/>"
        v4 = Markup("<input type='text'/>")     # 相当于django中的mark_safe,防止跨站XXS攻击
        return render_template('index.html',v1=v1,v2=v2,v3=v3,v4=v4,test=test)
    
    if __name__ == '__main__':
        app.run()
    View Code

    2. 模板语言

    {% extends 'layout.html' %}
    {%block body%}
        <p>{{v1}}</p>
        <ul>
            {% for item in v2 %}
            <li>{{item}}</li>
            {% endfor %}
        </ul>
        <ul>
            {% for k,v in v3.items() %} <!-- 与 django不同jinjia2需要加括号-->
                <li>{{k}}  {{v}}</li>
            {% endfor %}
        </ul>
    
        <p>{{v3.k1}}</p>
        <p>{{v3.get('k1')}}</p>
        <!--<p>{{v4|safe}}</p>-->
        <p>{{v4}}</p>
        <p>{{test(1,23)}}</p>
        <p>{{sb(1,2)}}</p>      <!--template_global可直接使用-->
        <p>{{1|db(2,3)}}</p>    <!--template_filter需要用管道符调用,管道符之前是第一个参数,括号中是其余的参数-->
    
        <!--宏,想函数一样的使用-->
        {% macro abc(name, type='text', value='') %}
            <input type="{{ type }}" name="{{ name }}" value="{{ value }}">
            <input type="{{ type }}" name="{{ name }}" value="{{ value }}">
            <input type="{{ type }}" name="{{ name }}" value="{{ value }}">
            <input type="{{ type }}" name="{{ name }}" value="{{ value }}">
        {% endmacro %}
        {{ abc('egon') }}
    {%endblock%}
    View Code

    3. layout

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <h1>模板</h1>
        {%block body%}{%endblock%}
    </body>
    </html>
    View Code

    五、flask-session

    1. session保存的原理

    session本质上操作的是字典。以字典形式保存在内存当中。

    flask默认方式,程序执行过程中,若干次操作session,首先保存在内存当中。

    在最后返回的前,通过cookie保存在浏览器,提升了执行效率,节省了请求的此书。

    其他框架可能会操作一次session,保存一次session到如数据库中。

    2. session配置的方式

    flask中的配置文件是一个flask.config.Config对象(继承字典),默认配置为:
        {
            'PERMANENT_SESSION_LIFETIME':           timedelta(days=31),    # session超时时间
            'SESSION_COOKIE_NAME':                  'session',    # session名称
            'SESSION_COOKIE_DOMAIN':                None,        # session支持的域名
            'SESSION_COOKIE_PATH':                  None,
            'SESSION_COOKIE_HTTPONLY':              True,
            'SESSION_COOKIE_SECURE':                False,
            'SESSION_REFRESH_EACH_REQUEST':         True,    # 每次访问重新计算session失效时间
        }
     
     
    from flask import Flask,session
     
    app = Flask(__name__)
     
    app.secret_key = 'adfadsfhjkhakljsdfh'
    app.config['SESSION_COOKIE_NAME'] = 'session_lvjing'
     
    @app.route('/index',endpoint='xxx')
    def index():
        session['xxx'] = 123
        return 'xxx'
     
    if __name__ == '__main__':
        app.run()
    View Code

    六、闪现(flash)

    在session的基础上,把值放入session,取的同时将值删除(pop)。

    如果普通的调用session保存传递,每次在session中都已存储了值,如果使用闪现则只会出现一次即消失。

    from flask import Flask,session,flash,request,get_flashed_messages,redirect
    
    app = Flask(__name__)
    
    app.secret_key = 'adfadsfhjkhakljsdfh'
    
    @app.route('/index')
    def index():
        msg = get_flashed_messages()
        # msg = session.get('msg','')
        print(msg)
        return 'xxx'
    
    @app.route('/login')
    def login():
        flash('登录成功')
        # session['msg'] = 111
        return redirect('/index')
    
    if __name__ == '__main__':
        app.run()
    

    七、 仿中间件之扩展

    扩展的默认执行顺序与django中的中间件一致,request根据先后顺序执行,response则相反,后进先出。

     1 from flask import Flask
     2 
     3 app = Flask(__name__)
     4 
     5 app.secret_key = 'adfadsfhjkhakljsdfh'
     6 
     7 
     8 # 在第一个用户访问时,执行之后不再执行,
     9 # 原理为将一个变量置为False,第一次访问时改为True,之后再次访问不再执行
    10 # @app.before_first_request
    11 # def process_first_request():
    12 #     print('process_first_request')
    13 
    14 
    15 @app.before_request
    16 def process_request1():
    17     print('process_request1')
    18 
    19 @app.after_request
    20 def process_response1(response):     # 响应中间件需要提供response参数,及返回response参数
    21     print('process_response1')
    22     return response
    23 
    24 @app.before_request
    25 def process_request2():
    26     print('process_request2')
    27 
    28 @app.after_request
    29 def process_response2(response):     # 响应中间件需要提供response参数,及返回response参数
    30     print('process_response2')
    31     return response
    32 
    33 
    34 @app.route('/index')
    35 def index():
    36     print('aaa')
    37     return 'xxx'
    38 
    39 
    40 if __name__ == '__main__':
    41     app.run()
    42 
    43 ------------------------------------
    44 
    45 process_request1
    46 process_request2
    47 aaa
    48 process_response2
    49 process_response1
    View Code
  • 相关阅读:
    kafka 消息推送报错"dial tcp: lookup iZ2ze2k3******7abjcsyZ on 219.141.140.10:53: no such host"
    MacBook安装Homebrew的国内安装脚本 告别龟速下载安装
    docker info命令的使用和返回结果描述
    Python requests.post方法中data与json参数区别
    redis master-slave python switch logic (升级版,序列七)
    ELKF日志收集系统
    MySQL 中的concat函数使用
    程序员的街舞“梦”
    第一份工作没有工资,信不信
    Java中的享元设计模式,涨姿势了!
  • 原文地址:https://www.cnblogs.com/yunweixiaoxuesheng/p/8359427.html
Copyright © 2011-2022 走看看