zoukankan      html  css  js  c++  java
  • Flask进阶

     一、路由系统

    1.路由

    @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'])

      以上五中都是可传入参数的路由,也是常用路由,所有的路由都基于以下对应关系来处理

    DEFAULT_CONVERTERS = {
        'default':          UnicodeConverter,
        'string':           UnicodeConverter,
        'any':              AnyConverter,
        'path':             PathConverter,
        'int':              IntegerConverter,
        'float':            FloatConverter,
        'uuid':             UUIDConverter,
    }

     2,反向生成url 

    在反向生成url的时候,必须导入url_for,即

    from flask import Flask, url_for

    endpoint("name")   #别名,相当于django中的name

    @app.route('/index',endpoint="xxx")  #endpoint是别名
    def index():
        v = url_for("xxx")
        print(v)
        return "index"
    
    @app.route('/zzz/<int:nid>',endpoint="aaa")  #endpoint是别名
    def zzz(nid):
        v = url_for("aaa",nid=nid)
        print(v)
        return "index2"

    3、@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,             子域名访问
                                                    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

      练习

    redirect_to:直接重定向,原url有参数时,跳转是也得传参,注意:不用加类型

    #/old
    @app.route('/old/<int:nid>',redirect_to="/new/<nid>")
    def old(nid):
        return "old"
    # /new
    @app.route('/new/<int:nid>')
    def new(nid):
        return "new"

     对url最后的/符号是否严格要求

    @app.route('/test',strict_slashes=True)  #当为True时,url后面必须不加斜杠
    def test():
        return "aaaaaaaa"
    @app.route('/test',strict_slashes=False)  #当为False时,url上加不加斜杠都行
    def test():
        return "aaaaaaaa" 

    子域名访问

    @app.route("/static_index", subdomain="admin")
    def static_index():
        return "admin.bjg.com"

    动态生成子域名

    @app.route("/index",subdomain='<xxxxx>')
    def index(xxxxx):
        return "%s.bjg.com" %(xxxxx,)

    Flask不支持正则,在扩展路由时,必须去继承BaseConverter

    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
    
        # 添加到converts中
        app.url_map.converters['regex'] = RegexConverter
    
        # 进行使用
        @app.route('/index/<regex("d+"):nid>',endpoint='xx')
        def index(nid):
            url_for('xx',nid=123)  #反向生成,就会去执行to_url方法
            return "Index"
    
        if __name__ == '__main__':
            app.run()

    二、视图函数

    1.Flask中的CBV模式

    def auth(func):
                def inner(*args, **kwargs):
                    result = func(*args, **kwargs)
                    return result
                return inner
    
            class IndexView(views.MethodView):
                # methods = ['POST']  #只允许POST请求访问
                decorators = [auth,]  #如果想给所有的get,post请求加装饰器,就可以这样来写,也可以单个指定
      
                def get(self):   #如果是get请求需要执行的代码
                    v = url_for('index')
                    print(v)
                    return "GET"
    
                def post(self):  #如果是post请求执行的代码
                    return "POST"
    
            app.add_url_rule('/index', view_func=IndexView.as_view(name='index'))  #name指定的是别名,会当做endpoint使用
    
            if __name__ == '__main__':
                app.run()

    2.Flask中的FBV模式

    两种方式:

    方式一:
        @app.route('/index',endpoint='xx')
        def index(nid):
            url_for('xx',nid=123)
            return "Index"
    
        方式二:
        def index(nid):
            url_for('xx',nid=123)
            return "Index"
    
        app.add_url_rule('/index',index)

    三、请求与响应

    from flask import Flask
        from flask import request
        from flask import render_template
        from flask import redirect
        from flask import make_response
    
        app = Flask(__name__)
    
    
        @app.route('/login.html', methods=['GET', "POST"])
        def login():
    
            # 请求相关信息
            # 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
    
    
            return "内容"
    
        if __name__ == '__main__':
            app.run()
    View Code
    from flask import Flask,url_for,request,redirect,render_template,jsonify,make_response
    from urllib.parse import urlencode,quote,unquote
    app = Flask(__name__)
    
    @app.route('/index',endpoint='xx')
    def index():
        from werkzeug.datastructures import ImmutableMultiDict
      =================
        # get_data = request.args
        # get_dict = get_data.to_dict()
        # get_dict['xx'] = '18'
        # url = urlencode(get_dict)
        # print(url)
      ====================
        # print(request.query_string)
        # print(request.args)
      ==========================
        # val = "%E6%8A%8A%E5%87%A0%E4%B8%AA"
        # print(unquote(val))   #吧上面这样的数据转换成中文
        #
        # return "Index"
    
        # return "Index"
        # return redirect()
        # return render_template()
        # return jsonify(name='alex',age='18')  #相当于JsonResponse
      =======================
        response = make_response('xxxxx')   ##如果是返回更多的值,cookie,headers,或者其他的就可用它
        response.headers['xxx'] = '123123'
        return response
    
    
    if __name__ == '__main__':
        # app.__call__
        app.run()

    四、模板语法

    1、模板的使用

    Flask使用的是Jinja2模板,所以其语法和Django无差别

    2、自定义模板方法

    Flask中自定义模板方法的方式和Bottle相似,创建一个函数并通过参数的形式传入render_template,如:

    <!DOCTYPE html>
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <h1>自定义函数</h1>
        {{ww()|safe}}
    
    </body>
    </html>
    
    html
    html
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from flask import Flask,render_template
    app = Flask(__name__)
     
     
    def wupeiqi():
        return '<h1>Wupeiqi</h1>'
     
    @app.route('/login', methods=['GET', 'POST'])
    def login():
        return render_template('login.html', ww=wupeiqi)
     
    app.run()
    
    run.py
    run.py
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    
    
        {% macro input(name, type='text', value='') %}
            <input type="{{ type }}" name="{{ name }}" value="{{ value }}">
        {% endmacro %}
    
        {{ input('n1') }}
    
        {% include 'tp.html' %}
    
        <h1>asdf{{ v.k1}}</h1>
    </body>
    </html>
    
    其他
    其他

    五、session

    除请求对象之外,还有一个 session 对象。它允许你在不同请求间存储特定用户的信息。它是在 Cookies 的基础上实现的,并且对 Cookies 进行密钥签名要使用会话,你需要设置一个密钥。

    • 设置:session['username'] = 'xxx'

    • 删除:session.pop('username', None)
    from flask import Flask, session, redirect, url_for, escape, request
     
    app = Flask(__name__)
     
    @app.route('/')
    def index():
        if 'username' in session:
            return 'Logged in as %s' % escape(session['username'])
        return 'You are not logged in'
     
    @app.route('/login', methods=['GET', 'POST'])
    def login():
        if request.method == 'POST':
            session['username'] = request.form['username']
            return redirect(url_for('index'))
        return '''
            <form action="" method="post">
                <p><input type=text name=username>
                <p><input type=submit value=Login>
            </form>
        '''
     
    @app.route('/logout')
    def logout():
        # remove the username from the session if it's there
        session.pop('username', None)
        return redirect(url_for('index'))
     
    # set the secret key.  keep this really secret:
    app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'
    基本使用
    pip3 install Flask-Session
            
            run.py
                from flask import Flask
                from flask import session
                from pro_flask.utils.session import MySessionInterface
                app = Flask(__name__)
    
                app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'
                app.session_interface = MySessionInterface()
    
                @app.route('/login.html', methods=['GET', "POST"])
                def login():
                    print(session)
                    session['user1'] = 'alex'
                    session['user2'] = 'alex'
                    del session['user2']
    
                    return "内容"
    
                if __name__ == '__main__':
                    app.run()
    
            session.py
                #!/usr/bin/env python
                # -*- coding:utf-8 -*-
                import uuid
                import json
                from flask.sessions import SessionInterface
                from flask.sessions import SessionMixin
                from itsdangerous import Signer, BadSignature, want_bytes
    
    
                class MySession(dict, SessionMixin):
                    def __init__(self, initial=None, sid=None):
                        self.sid = sid
                        self.initial = initial
                        super(MySession, self).__init__(initial or ())
    
    
                    def __setitem__(self, key, value):
                        super(MySession, self).__setitem__(key, value)
    
                    def __getitem__(self, item):
                        return super(MySession, self).__getitem__(item)
    
                    def __delitem__(self, key):
                        super(MySession, self).__delitem__(key)
    
    
    
                class MySessionInterface(SessionInterface):
                    session_class = MySession
                    container = {}
    
                    def __init__(self):
                        import redis
                        self.redis = redis.Redis()
    
                    def _generate_sid(self):
                        return str(uuid.uuid4())
    
                    def _get_signer(self, app):
                        if not app.secret_key:
                            return None
                        return Signer(app.secret_key, salt='flask-session',
                                      key_derivation='hmac')
    
                    def open_session(self, app, request):
                        """
                        程序刚启动时执行,需要返回一个session对象
                        """
                        sid = request.cookies.get(app.session_cookie_name)
                        if not sid:
                            sid = self._generate_sid()
                            return self.session_class(sid=sid)
    
                        signer = self._get_signer(app)
                        try:
                            sid_as_bytes = signer.unsign(sid)
                            sid = sid_as_bytes.decode()
                        except BadSignature:
                            sid = self._generate_sid()
                            return self.session_class(sid=sid)
    
                        # session保存在redis中
                        # val = self.redis.get(sid)
                        # session保存在内存中
                        val = self.container.get(sid)
    
                        if val is not None:
                            try:
                                data = json.loads(val)
                                return self.session_class(data, sid=sid)
                            except:
                                return self.session_class(sid=sid)
                        return self.session_class(sid=sid)
    
                    def save_session(self, app, session, response):
                        """
                        程序结束前执行,可以保存session中所有的值
                        如:
                            保存到resit
                            写入到用户cookie
                        """
                        domain = self.get_cookie_domain(app)
                        path = self.get_cookie_path(app)
                        httponly = self.get_cookie_httponly(app)
                        secure = self.get_cookie_secure(app)
                        expires = self.get_expiration_time(app, session)
    
                        val = json.dumps(dict(session))
    
                        # session保存在redis中
                        # self.redis.setex(name=session.sid, value=val, time=app.permanent_session_lifetime)
                        # session保存在内存中
                        self.container.setdefault(session.sid, val)
    
                        session_id = self._get_signer(app).sign(want_bytes(session.sid))
    
                        response.set_cookie(app.session_cookie_name, session_id,
                                            expires=expires, httponly=httponly,
                                            domain=domain, path=path, secure=secure)
    
    自定义Session
    自定义session
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    """
    pip3 install redis
    pip3 install flask-session
    
    """
    
    
    from flask import Flask, session, redirect
    from flask.ext.session import Session
    
    
    app = Flask(__name__)
    app.debug = True
    app.secret_key = 'asdfasdfasd'
    
    
    app.config['SESSION_TYPE'] = 'redis'
    from redis import Redis
    app.config['SESSION_REDIS'] = Redis(host='192.168.0.94',port='6379')
    Session(app)
    
    
    @app.route('/login')
    def login():
        session['username'] = 'alex'
        return redirect('/index')
    
    
    @app.route('/index')
    def index():
        name = session['username']
        return name
    
    
    if __name__ == '__main__':
        app.run()
    
    第三方session
    第三方session

    关于session的配置

     app.config['SESSION_COOKIE_NAME'] = 'session_lvning'
    复制代码
    - session超时时间如何设置?      'PERMANENT_SESSION_LIFETIME':           timedelta(days=31)
     以下是跟session相关的配置文件
    """
                'SESSION_COOKIE_NAME':                  'session',
                'SESSION_COOKIE_DOMAIN':                None,
                'SESSION_COOKIE_PATH':                  None,
                'SESSION_COOKIE_HTTPONLY':              True,
                'SESSION_COOKIE_SECURE':                False,
                'SESSION_REFRESH_EACH_REQUEST':         True,  #是否每次都跟新
                'PERMANENT_SESSION_LIFETIME':           timedelta(days=31)
    复制代码

    六、闪现

    Flask中闪现是基于session来实现的,而session存在于服务器端的一个字典里,把session保存起来,取一次值,里面还是有数据,直到你完全删除后才没有值了。

    闪现的使用

    from flask import Flask,session,Session,flash,get_flashed_messages,redirect,render_template,request
    app = Flask(__name__)
    app.secret_key ='sdfsdfsdf'
    
    @app.route('/users')
    def users():
        # msg = request.args.get('msg','')
        # msg = session.get('msg')
        # if msg:
        #     del session['msg']
    
        v = get_flashed_messages()
        print(v)
        msg = ''
        return render_template('users.html',msg=msg)
    
    @app.route('/useradd')
    def user_add():
        # 在数据库中添加一条数据
        # 假设添加成功,在跳转到列表页面时,显示添加成功
        # 方式一
        # return redirect('/users?msg=添加成功')
        # 方式二
        # session['msg'] = '添加成功'
        # 方式三
        flash('添加成功')
        return redirect('/users')
    
    
    if __name__ == '__main__':
        app.run(port=5001)

    六、扩展

    注:

      1.Flask中的扩展相当于django中的中间件

      2.Flask中是不支持正则的,通过扩展Flask的路由系统,用到了BaseConverter来扩展路由。

      3.@app.before_first_request:表示,当程序运行起来,第一个请求来的时候就只执行一次,下次再来就不会在执行了

    具体使用

    from flask import Flask,session,Session,flash,get_flashed_messages,redirect,render_template,request
    app = Flask(__name__)
    app.secret_key ='sdfsdfsdf'
    
    @app.before_request
    def process_request1():
        print('process_request1')
    
    @app.after_request
    def process_response1(response):
        print('process_response1')
        return response
    
    
    @app.before_request
    def process_request2():
        print('process_request2')
    
    @app.after_request
    def process_response2(response):   #参数也得有
        print('process_response2')
        return response   #必须有返回值
    
    
    @app.route('/index')
    def index():
        print('index')
        return 'Index'
    
    @app.route('/order')
    def order():
        print('order')
        return 'order'
    
    @app.route('/test')
    def test():
        print('test')
        return 'test'
    
    if __name__ == '__main__':
        app.run()

    运行结果如下:

  • 相关阅读:
    Python 存储引擎 数据类型 主键
    Python 数据库
    Python 线程池进程池 异步回调 协程 IO模型
    Python GIL锁 死锁 递归锁 event事件 信号量
    Python 进程间通信 线程
    Python 计算机发展史 多道技术 进程 守护进程 孤儿和僵尸进程 互斥锁
    Python 异常及处理 文件上传事例 UDP socketserver模块
    Python socket 粘包问题 报头
    Django基础,Day7
    Django基础,Day6
  • 原文地址:https://www.cnblogs.com/moning/p/8214303.html
Copyright © 2011-2022 走看看