• flask基础使用:配置信息、路由、请求和响应、视图、session、蓝图、特殊装饰器、message、模板


    1、配置文件

     default_config = ImmutableDict(
            {
                "ENV": None,
                "DEBUG": None,
                "TESTING": False,
                "PROPAGATE_EXCEPTIONS": None,
                "PRESERVE_CONTEXT_ON_EXCEPTION": None,
                "SECRET_KEY": None,
                "PERMANENT_SESSION_LIFETIME": timedelta(days=31),
                "USE_X_SENDFILE": False,
                "SERVER_NAME": None,
                "APPLICATION_ROOT": "/",
                "SESSION_COOKIE_NAME": "session",
                "SESSION_COOKIE_DOMAIN": None,
                "SESSION_COOKIE_PATH": None,
                "SESSION_COOKIE_HTTPONLY": True,
                "SESSION_COOKIE_SECURE": False,
                "SESSION_COOKIE_SAMESITE": None,
                "SESSION_REFRESH_EACH_REQUEST": True,
                "MAX_CONTENT_LENGTH": None,
                "SEND_FILE_MAX_AGE_DEFAULT": timedelta(hours=12),
                "TRAP_BAD_REQUEST_ERRORS": None,
                "TRAP_HTTP_EXCEPTIONS": False,
                "EXPLAIN_TEMPLATE_LOADING": False,
                "PREFERRED_URL_SCHEME": "http",
                "JSON_AS_ASCII": True,
                "JSON_SORT_KEYS": True,
                "JSONIFY_PRETTYPRINT_REGULAR": False,
                "JSONIFY_MIMETYPE": "application/json",
                "TEMPLATES_AUTO_RELOAD": None,
                "MAX_COOKIE_SIZE": 4093,
            }
        )
    默认配置信息

      配置方式1:

    app = Flask(__name__)
    app.config["DEBUG"] = True

     

      config继承字典,所以字典有方法它都能用

      配置方式2:

    class Foo(object):
        DEBUG = False
        TEMPLATES = "templates"
        
        
    class Dev(object):
        DEBUG = True
        TEMPLATES = "templates"
    settings.py
    app = Flask(__name__)
    # app.config.from_object("settings.Foo")
    app.config.from_object("settings.Dev")

      更多配置方式:

    flask中的配置文件是一个flask.config.Config对象(继承字典),默认配置为:
        {
            'DEBUG':                                get_debug_flag(default=False),  是否开启Debug模式
            'TESTING':                              False,                          是否开启测试模式
            'PROPAGATE_EXCEPTIONS':                 None,                          
            'PRESERVE_CONTEXT_ON_EXCEPTION':        None,
            'SECRET_KEY':                           None,
            'PERMANENT_SESSION_LIFETIME':           timedelta(days=31),
            'USE_X_SENDFILE':                       False,
            'LOGGER_NAME':                          None,
            'LOGGER_HANDLER_POLICY':               'always',
            'SERVER_NAME':                          None,
            'APPLICATION_ROOT':                     None,
            '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,
            'MAX_CONTENT_LENGTH':                   None,
            'SEND_FILE_MAX_AGE_DEFAULT':            timedelta(hours=12),
            'TRAP_BAD_REQUEST_ERRORS':              False,
            'TRAP_HTTP_EXCEPTIONS':                 False,
            'EXPLAIN_TEMPLATE_LOADING':             False,
            'PREFERRED_URL_SCHEME':                 'http',
            'JSON_AS_ASCII':                        True,
            'JSON_SORT_KEYS':                       True,
            'JSONIFY_PRETTYPRINT_REGULAR':          True,
            'JSONIFY_MIMETYPE':                     'application/json',
            'TEMPLATES_AUTO_RELOAD':                None,
        }
     
    方式一:
        app.config['DEBUG'] = True
     
        PS: 由于Config对象本质上是字典,所以还可以使用app.config.update(...)
     
    方式二:
        app.config.from_pyfile("python文件名称")
            如:
                settings.py
                    DEBUG = True
     
                app.config.from_pyfile("settings.py")
     
        app.config.from_envvar("环境变量名称")
            环境变量的值为python文件名称名称,内部调用from_pyfile方法
     
     
        app.config.from_json("json文件名称")
            JSON文件名称,必须是json格式,因为内部会执行json.loads
     
        app.config.from_mapping({'DEBUG':True})
            字典格式
     
        app.config.from_object("python类或类的路径")
     
            app.config.from_object('pro_flask.settings.TestingConfig')
     
            settings.py
     
                class Config(object):
                    DEBUG = False
                    TESTING = False
                    DATABASE_URI = 'sqlite://:memory:'
     
                class ProductionConfig(Config):
                    DATABASE_URI = 'mysql://user@localhost/foo'
     
                class DevelopmentConfig(Config):
                    DEBUG = True
     
                class TestingConfig(Config):
                    TESTING = True
     
            PS: 从sys.path中已经存在路径开始写
         
     
        PS: settings.py文件默认路径要放在程序root_path目录,如果instance_relative_config为True,则就是instance_path目录
    
    配置文件
    配置方式

    2、路由系统

    @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,
    }
    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, 子域名访问
    route参数

      简单使用:

    @app.route('/index/<username>')
    def index(username):
        print(username)
        return "index"
    
    # @app.route('/index/<int:id>')
    # def index(id):
    #     print(id)
    #     return "index"
    def auth(func):
                def inner(*args, **kwargs):
                    print('before')
                    result = func(*args, **kwargs)
                    print('after')
                    return result
    
            return inner
    
            @app.route('/index.html',methods=['GET','POST'],endpoint='index')
            @auth
            def index():
                return 'Index'def index():
                return "Index"
    
            self.add_url_rule(rule='/index.html', endpoint="index", view_func=index, methods=["GET","POST"])
            or
            app.add_url_rule(rule='/index.html', endpoint="index", view_func=index, methods=["GET","POST"])
            app.view_functions['index'] = index
    
    
            或
            def auth(func):
                def inner(*args, **kwargs):
                    print('before')
                    result = func(*args, **kwargs)
                    print('after')
                    return result
    
            return inner
    
            class IndexView(views.View):
                methods = ['GET']
                decorators = [auth, ]
    
                def dispatch_request(self):
                    print('Index')
                    return 'Index!'
    
            app.add_url_rule('/index', view_func=IndexView.as_view(name='index'))  # name=endpoint
    class IndexView(views.MethodView):
                methods = ['GET']
                decorators = [auth, ]
    
                def get(self):
                    return 'Index.GET'
    
                def post(self):
                    return 'Index.POST'
    
    
            app.add_url_rule('/index', view_func=IndexView.as_view(name='index'))  # name=endpoint
    
    
    
    
            @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()
            
    
    a.注册路由原理
    注册路由原理,带参数的装饰器
    from flask import Flask, views, url_for
                from werkzeug.routing import BaseConverter
    
                app = Flask(import_name=__name__)
    
    
                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
    
                # 添加到flask中
                app.url_map.converters['regex'] = RegexConverter
    
    
                @app.route('/index/<regex("d+"):nid>')
                def index(nid):
                    print(url_for('index', nid='888'))
                    return 'Index'
    
    
                if __name__ == '__main__':
                    app.run()
    
    b. 自定制正则路由匹配
    自定义正则路由匹配

       反向生成:url_for

    from flask import Flask, url_for
    endpoint("name")   #别名,相当于django中的name
    @app.route('/')
    def index1():
        url = url_for("aaa")
        print(url)  # /set
        return "Index1"
    
    
    @app.route('/set', endpoint="aaa")
    def index2():
        return 'ok'

       通过add_url_rule方法添加路由:因为route内部就是调用的flask这个方法,所以我们可以在外部直接覆盖它          

          

    def list_student(nid):
        print(nid)
        return render_template("student.html")
    
    
    app.add_url_rule('/student', None, list_student)

    3、视图

      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)

      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()

    4、请求和响应相关

      请求相关:

            # 请求相关信息
            # request.method  # 请求方式
            # request.args    # 获取路径中的条件 ?username=aike
            # request.form   # 获取post请求的数据
            # request.values
            # request.cookies  #获取cookie和session
            # 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')  # 删除响应头cookies
            # response.set_cookie('key', 'value')
            # response.headers['X-Something'] = 'A value'  #设置响应头
            # return response        

    5、模板渲染

      使用:Flask使用的是Jinja2模板,所以其语法和Django无差别,并且更接近python原生语法

        母版、块、过滤器等,使用无区别:参考django

      他可以传入函数在模板中使用:

        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
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from flask import Flask,render_template
    app = Flask(__name__)
     
     
    def func():
        return '<h1>Wupeiqi</h1>'
     
    @app.route('/login', methods=['GET', 'POST'])
    def login():
        return render_template('login.html', ww=func)
     
    if __name__ == '__main__':
        app.run()
    app.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 进行密钥签名要使用会话,你需要设置一个密钥。

    app.secret_key = "lllasdka"  # 设置秘钥
    设置:session['username'] = 'xxx'
    
    删除:session.pop('username', None)
    
            del session['username']
    from flask import Flask, render_template, redirect, request, session
    import functools
    
    app = Flask(__name__)
    app.secret_key = "lllasdka"  
    
    
    def func(f):
        @functools.wraps(f)
        def inner(*args, **kwargs):
            if not session.get("token"):
                return redirect("/login")
            ret = f(*args, **kwargs)
            del session["token"]
            return ret
        return inner
    
    
    @app.route('/index')
    @func
    def index():
        return render_template("index.html")
    
    
    @app.route('/login', methods=["GET", "POST"])
    def login():
        if request.method == "GET":
            return render_template("index.html")
        user = request.form.get("user")
        pwd = request.form.get("pwd")
        if user == "aike" and pwd == "666":
            session["token"] = 1
            return "登录成功"
        return render_template("index.html", error="用户名或密码错误")
    
    
    @app.route("/index2")
    @func
    def index2():
        return "ok"
    
    
    if __name__ == '__main__':
        app.run()
    基本使用
     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
    #!/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

    7、message

      message是一个基于Session实现的用于保存数据的集合,其特点是:使用一次就删除。实现原理就是每请求一次就像session中添加一条值在一个列表中,取一次就pop这条session

    from flask import Flask, render_template, redirect, request, session ,get_flashed_messages, flash
    
    app = Flask(__name__)
    app.secret_key = "lllasdka" 
    app.config.from_object("settings.Foo")
    
    @app.route('/')
    def index1():
        messages = get_flashed_messages()  # 取出存入的值
        print(messages)  # 1
        return "Index1"
    
    
    @app.route('/set')
    def index2():
        v = request.args.get('p')  # ?p=1
        flash(v) 
        return 'ok'

    8、中间件

      与django的中间件不同,中间件的执行在路由之前,在flask当中,__call__是整个请求的流程的开始,它返回wsgi_app的执行,所以我们可以重写它进行请求前的操作

    from flask import Flask, flash, redirect, render_template, request
     
    app = Flask(__name__)
    app.secret_key = 'some_secret'
     
    @app.route('/')
    def index1():
        return render_template('index.html')
     
    @app.route('/set')
    def index2():
        v = request.args.get('p')
        flash(v)
        return 'ok'
     
    class MiddleWare:
        def __init__(self,wsgi_app):
            self.wsgi_app = wsgi_app
     
        def __call__(self, *args, **kwargs):
     
            return self.wsgi_app(*args, **kwargs)
     
    if __name__ == "__main__":
        app.wsgi_app = MiddleWare(app.wsgi_app)
        app.run(port=9999)

    9、蓝图

      建议阅读官方文档:跳转

    Flask 中蓝图有以下用途:
    
    把一个应用分解为一套蓝图。这是针对大型应用的理想方案:一个项目可以实例化 一个应用,初始化多个扩展,并注册许多蓝图。
    
    在一个应用的 URL 前缀和(或)子域上注册一个蓝图。 URL 前缀和(或)子域的 参数成为蓝图中所有视图的通用视图参数(缺省情况下)。
    
    使用不同的 URL 规则在应用中多次注册蓝图。
    
    通过蓝图提供模板过滤器、静态文件、模板和其他工具。蓝图不必执行应用或视图 函数。
    
    当初始化一个 Flask 扩展时,为以上任意一种用途注册一个蓝图。
    
    Flask 中的蓝图不是一个可插拨的应用,因为它不是一个真正的应用,而是一套可以 注册在应用中的操作,并且可以注册多次。那么为什么不使用多个应用对象呢?可以 使用多个应用对象(参见 应用调度 ),但是这样会导致每个应用都使 用自己独立的配置,且只能在 WSGI 层中管理应用。
    
    而如果使用蓝图,那么应用会在 Flask 层中进行管理,共享配置,通过注册按需改 变应用对象。蓝图的缺点是一旦应用被创建后,只有销毁整个应用对象才能注销蓝图。
    为什么使用蓝图
    蓝图的基本概念是:在蓝图被注册到应用之后,生成所要执行的操作的集合。当分配请求时, Flask 会把蓝图和视图函数关联起来,并生成相对应的URL 。
    概念

      使用:

        1、创建蓝图对象:导入模块Blueprint

    name -在名称蓝图。将在每个端点名称之前。
    
    import_name – 蓝图包的名称,通常为 __name__。这有助于找到root_path该蓝图。
    
    static_folder –包含静态文件的文件夹,该文件应由蓝图的静态路由提供。该路径相对于蓝图的根路径。蓝图静态文件默认为禁用。
    
    static_url_path –用于提供静态文件的URL。默认为static_folder。如果该蓝图没有url_prefix,则该应用程序的静态路由将优先,并且该蓝图的静态文件将不可访问。
    
    template_folder –带有模板的文件夹,应将其添加到应用程序的模板搜索路径中。该路径是相对于 蓝图的根路径。蓝图模板默认为禁用。蓝图模板的优先级低于应用程序模板文件夹中的优先级。
    
    url_prefix –前缀在所有蓝图 URL上的路径,以使它们与应用程序的其余路由区分开。
    
    子域 – 默认情况下,蓝图路由将匹配的子域。
    
    url_defaults –默认情况下,蓝图路由将接收的默认值。
    
    root_path –默认情况下,蓝图将基于import_name。在某些情况下,此自动检测可能会失败,因此可以手动指定路径。
    Blueprint参数
    from flask import Blueprint, render_template
    
    student = Blueprint("student", __name__, template_folder="templates", static_folder="statics", static_url_path="static")
    
    
    # student = Blueprint("student", __name__, static_url_path="static")
    
    @student.before_request  # 只对当前蓝图对象有效
    def xxx():
        print("sss")
    
    
    @student.route("/student")
    def list_student():
        return render_template("student.html")

        2、注册蓝图 

    blueprint:必须给定,需要注册的一个蓝图对象
    url_prefix:给请求的路由添加一个前缀:127.0.0.1:8000/api/course
    subdomain:路由将匹配这个子域。
    url_defaults: 给路由匹配的视图函数添加默认值
    
    options:传递额外的关键字参数
    注册时的参数
    from flask import Flask
    from .views.course import course
    from .views.student import student
    from .views.userinfo import user
    
         app = Flask(__name__)    
        
        @app.before_request   # 对所有注册的蓝图都有效
        def xx():
            print("xxxxx")
    
        app.register_blueprint(course, url_prefix="/api")
        app.register_blueprint(student, url_prefix="")
        app.register_blueprint(user, url_prefix="")

      使用蓝图应该注意的地方:

        创建蓝图对象时传入的static_folder与template_folder参数,默认还是先找Flask设置的默认参数,flask没有再找蓝图设置的。

        注册蓝图时的url_prefix参数不传时,可能会报错,错误信息为“”urls must start with a leading slash“”,最好是传入一个空字符串

        若想为单独的一类的视图使用before_request、after_request等特殊的装饰器时,需要在这类视图中通过蓝图对象添加装饰器即可,而不是flask对象。flask对象使用的特殊装饰器对全局有效

        

    10、特殊装饰器

      before_request:视图执行前需要执行的函数

      after_request:视图执行完毕后需要执行的函数

      before_first_request:第一次请求执行的函数,后面的请求不再执行

      template_global:全局定义函数,所有的视图不传入这个函数也可以在模板中使用:{{函数名(参数1,参数2)}} 

      template_filter:与global一样,只是使用方式不一样,但是这个能在模板中当做是if条件:{{ 参数1 | 函数名(参数2,参数3)}}

      errorhandler:自定义错误信息如何在前端展示

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from flask import Flask, Request, render_template
    
    app = Flask(__name__, template_folder='templates')
    app.debug = True
    
    
    @app.before_first_request
    def before_first_request1():
        print('before_first_request1')
    
    
    @app.before_first_request
    def before_first_request2():
        print('before_first_request2')
    
    
    @app.before_request
    def before_request1():
        Request.nnn = 123
        print('before_request1')
    
    
    @app.before_request
    def before_request2():
        print('before_request2')
    
    
    @app.after_request
    def after_request1(response):
        print('before_request1', response)
        return response
    
    
    @app.after_request
    def after_request2(response):
        print('before_request2', response)
        return response
    
    
    @app.errorhandler(404)
    def page_not_found(error):
        return 'This page does not exist', 404
    
    
    @app.template_global()
    def sb(a1, a2):
        return a1 + a2
    
    
    @app.template_filter()
    def db(a1, a2, a3):
        return a1 + a2 + a3
    
    
    @app.route('/')
    def hello_world():
        return render_template('hello.html')
    
    
    if __name__ == '__main__':
        app.run()
    View Code
  • 相关阅读:
    java socket知识点
    java io流缓冲理解
    如何理解java回电话
    它们的定义Adapterg在etView( )正在使用View.setTag()与不同的是不使用。
    打造你自己ajax上传图片
    POJ 1166 The Clocks
    spring-framework-3.2.4.RELEASE 综合hibernate-release-4.3.5.Final一个错误Caused by: java.lang.NoClassDefFound
    [Android]Volley源代码分析(店)应用
    金融脱媒砸进?
    音乐家演奏乐器
  • 原文地址:https://www.cnblogs.com/aizhinong/p/12728861.html
Copyright © 2020-2023  润新知