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
原文地址:https://www.cnblogs.com/aizhinong/p/12728861.html