Flask - 官方文档阅读 - 基础总结

目录

零、学习资料

一、简单介绍

1-1 Werkzeug简介

二、简单使用

三、调试模式 两种方式

四、url路由基本使用

4-1 路由的变量规则

4-2 唯一 URL / 重定向行为

4-3 构造URL

五、HTTP方法

扫描二维码关注公众号,回复: 5169016 查看本文章

六、静态文件

七、模板渲染 - 基于jinja2模板引擎实现

八、请求数据访问

8-1 环境局部变量

8-2 Request对象

8-2-1 args属性 - 访问URL提交的参数(/…?key=value)

九、文件上传

9-1 filename属性 - 查看上传前文件在客户端的文件名

十、Cookies

十一、重定向和错误 - redirect()、abort()

11- 1 errorhandler() 装饰器 - 定制错误页面

十二、响应对象 make_response() - 操纵Flask把返回值转换为响应对象的逻辑

十三、session对象

十四、消息闪现

十五、日志记录

十六、整合WSGI中间件


零、学习资料

官方文档 - 全英文

官网文档 - 中译

中文文档目录

jinja2 - 官方文档 - 全英

jinja2 - 官方文档 - 中译

Werkzeug - 官方文档 - 全英

一、简单介绍

Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架

Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后触发Flask框架,开发人员基于Flask框架提供的功能对请求进行相应的处理,并返回给用户。

如果要返回给用户复杂的内容时,需要借助jinja2模板来实现对模板的处理,即:将模板和数据进行渲染,将渲染后的字符串返回给用户浏览器。

“微”(micro) 并不表示你需要把整个 Web 应用塞进单个 Python 文件(虽然确实可以 ),也不意味着 Flask 在功能上有所欠缺。微框架中的“微”意味着 Flask 旨在保持核心简单而易于扩展。Flask 不会替你做出太多决策——比如使用何种数据库。而那些 Flask 所选择的——比如使用何种模板引擎——则很容易替换。除此之外的一切都由可由你掌握。

默认情况下,Flask 不包含数据库抽象层、表单验证,或是其它任何已有多种库可以胜任的功能。然而,Flask 支持用扩展来给应用添加这些功能,如同是 Flask 本身实现的一样。众多的扩展提供了数据库集成、表单验证、上传处理、各种各样的开放认证技术等功能。Flask 也许是“微小”的,但它已准备好在需求繁杂的生产环境中投入使用

1-1 Werkzeug简介

Werkzeug是一个WSGI工具包,他可以作为一个Web框架的底层库。

 werkzeug 不是一个web服务器,也不是一个web框架,而是一个工具包,官方的介绍说是一个 WSGI 工具包,它可以作为一个 Web 框架的底层库,因为它封装好了很多 Web 框架的东西,例如 Request,Response 等等

'''
代码示例
'''
from werkzeug.wrappers import Request, Response

@Request.application
def hello(request):
    return Response('Hello World!')

if __name__ == '__main__':
    from werkzeug.serving import run_simple
    run_simple('localhost', 4000, hello)

二、简单使用

from flask import Flask

# 实例化产生一个Flask对象
app = Flask(__name__)
# 将 '/'和视图函数hello_workd的对应关系添加到路由中
@app.route('/') # 1. v=app.route('/') 2. v(hello_world)
def hello_world():
    return 'Hello World!'

if __name__ == '__main__':
    app.run() # 最终调用了run_simple()

源码分析

# flask实例化
    def __init__(
        self,
        import_name, # 应用程序包的名称
        static_url_path=None, # 可用于为web上的静态文件指定不同的路径。默认为“static_folder”文件夹的名称。
        static_folder='static', # 包含静态文件的文件夹,这些文件应该在'static_url_path'处提供。默认为应用程序根路径中的“静态”文件夹。
        static_host=None, # 添加静态路由时要使用的主机。默认为没有。当使用'host_match_true' 和配置的static_folder 时需要。
        host_matching=False,# 设置“url_map.host_matching“属性。默认值为False。
        subdomain_matching=False, # 在匹配路由时,考虑与:data: 'SERVER_NAME'相关的子域。默认值为False。
        template_folder='templates', # 包含应用程序应该使用的模板的文件夹。默认为应用程序根路径中的“模板”文件夹。
        instance_path=None, # 应用程序的可选实例路径。默认情况下,包或模块旁边的文件夹“instance”被认为是实例路径。
        instance_relative_config=False, # 如果将用于加载配置的相对文件名设置为“True”,则假定它相对于实例路径,而不是相对于应用程序根目录。
        root_path=None # Flask默认情况下会自动计算应用程序根目录的路径。在某些情况下,这是无法实现的(例如,如果包是Python 3命名空间包),需要手动定义。
    ):

"""
    The flask object implements a WSGI application and acts as the central
    object.  It is passed the name of the module or package of the
    application.  Once it is created it will act as a central registry for
    the view functions, the URL rules, template configuration and much more.

    The name of the package is used to resolve resources from inside the
    package or the folder the module is contained in depending on if the
    package parameter resolves to an actual python package (a folder with
    an :file:`__init__.py` file inside) or a standard module (just a ``.py`` file).

    For more information about resource loading, see :func:`open_resource`.

    Usually you create a :class:`Flask` instance in your main module or
    in the :file:`__init__.py` file of your package like this::

        from flask import Flask
        app = Flask(__name__)

    .. admonition:: About the First Parameter

        The idea of the first parameter is to give Flask an idea of what
        belongs to your application.  This name is used to find resources
        on the filesystem, can be used by extensions to improve debugging
        information and a lot more.

        So it's important what you provide there.  If you are using a single
        module, `__name__` is always the correct value.  If you however are
        using a package, it's usually recommended to hardcode the name of
        your package there.

        For example if your application is defined in :file:`yourapplication/app.py`
        you should create it with one of the two versions below::

            app = Flask('yourapplication')
            app = Flask(__name__.split('.')[0])

        Why is that?  The application will work even with `__name__`, thanks
        to how resources are looked up.  However it will make debugging more
        painful.  Certain extensions can make assumptions based on the
        import name of your application.  For example the Flask-SQLAlchemy
        extension will look for the code in your application that triggered
        an SQL query in debug mode.  If the import name is not properly set
        up, that debugging information is lost.  (For example it would only
        pick up SQL queries in `yourapplication.app` and not
        `yourapplication.views.frontend`)

    .. versionadded:: 0.7
       The `static_url_path`, `static_folder`, and `template_folder`
       parameters were added.

    .. versionadded:: 0.8
       The `instance_path` and `instance_relative_config` parameters were
       added.

    .. versionadded:: 0.11
       The `root_path` parameter was added.

    .. versionadded:: 1.0
       The ``host_matching`` and ``static_host`` parameters were added.

    .. versionadded:: 1.0
       The ``subdomain_matching`` parameter was added. Subdomain
       matching needs to be enabled manually now. Setting
       :data:`SERVER_NAME` does not implicitly enable it.

    :param import_name: the name of the application package
    :param static_url_path: can be used to specify a different path for the
                            static files on the web.  Defaults to the name
                            of the `static_folder` folder.
    :param static_folder: the folder with static files that should be served
                          at `static_url_path`.  Defaults to the ``'static'``
                          folder in the root path of the application.
    :param static_host: the host to use when adding the static route.
        Defaults to None. Required when using ``host_matching=True``
        with a ``static_folder`` configured.
    :param host_matching: set ``url_map.host_matching`` attribute.
        Defaults to False.
    :param subdomain_matching: consider the subdomain relative to
        :data:`SERVER_NAME` when matching routes. Defaults to False.
    :param template_folder: the folder that contains the templates that should
                            be used by the application.  Defaults to
                            ``'templates'`` folder in the root path of the
                            application.
    :param instance_path: An alternative instance path for the application.
                          By default the folder ``'instance'`` next to the
                          package or module is assumed to be the instance
                          path.
    :param instance_relative_config: if set to ``True`` relative filenames
                                     for loading the config are assumed to
                                     be relative to the instance path instead
                                     of the application root.
    :param root_path: Flask by default will automatically calculate the path
                      to the root of the application.  In certain situations
                      this cannot be achieved (for instance if the package
                      is a Python 3 namespace package) and needs to be
                      manually defined.
    """
# 路由
    def route(self, rule, **options):
        """A decorator that is used to register a view function for a
        given URL rule.  This does the same thing as :meth:`add_url_rule`
        but is intended for decorator usage::

            @app.route('/')
            def index():
                return 'Hello World'

        For more information refer to :ref:`url-route-registrations`.

        :param rule: the URL rule as string
        :param endpoint: the endpoint for the registered URL rule.  Flask
                         itself assumes the name of the view function as
                         endpoint
        :param options: the options to be forwarded to the underlying
                        :class:`~werkzeug.routing.Rule` object.  A change
                        to Werkzeug is handling of method options.  methods
                        is a list of methods this rule should be limited
                        to (``GET``, ``POST`` etc.).  By default a rule
                        just listens for ``GET`` (and implicitly ``HEAD``).
                        Starting with Flask 0.6, ``OPTIONS`` is implicitly
                        added and handled by the standard request handling.
        """
        def decorator(f):
            endpoint = options.pop('endpoint', None)
            self.add_url_rule(rule, endpoint, f, **options)
            return f
        return decorator
# 执行run
    def run(self, host=None, port=None, debug=None,
            load_dotenv=True, **options):
        """Runs the application on a local development server.

        Do not use ``run()`` in a production setting. It is not intended to
        meet security and performance requirements for a production server.
        Instead, see :ref:`deployment` for WSGI server recommendations.

        If the :attr:`debug` flag is set the server will automatically reload
        for code changes and show a debugger in case an exception happened.

        If you want to run the application in debug mode, but disable the
        code execution on the interactive debugger, you can pass
        ``use_evalex=False`` as parameter.  This will keep the debugger's
        traceback screen active, but disable code execution.

        It is not recommended to use this function for development with
        automatic reloading as this is badly supported.  Instead you should
        be using the :command:`flask` command line script's ``run`` support.

        .. admonition:: Keep in Mind

           Flask will suppress any server error with a generic error page
           unless it is in debug mode.  As such to enable just the
           interactive debugger without the code reloading, you have to
           invoke :meth:`run` with ``debug=True`` and ``use_reloader=False``.
           Setting ``use_debugger`` to ``True`` without being in debug mode
           won't catch any exceptions because there won't be any to
           catch.

        :param host: the hostname to listen on. Set this to ``'0.0.0.0'`` to
            have the server available externally as well. Defaults to
            ``'127.0.0.1'`` or the host in the ``SERVER_NAME`` config variable
            if present.
        :param port: the port of the webserver. Defaults to ``5000`` or the
            port defined in the ``SERVER_NAME`` config variable if present.
        :param debug: if given, enable or disable debug mode. See
            :attr:`debug`.
        :param load_dotenv: Load the nearest :file:`.env` and :file:`.flaskenv`
            files to set environment variables. Will also change the working
            directory to the directory containing the first file found.
        :param options: the options to be forwarded to the underlying Werkzeug
            server. See :func:`werkzeug.serving.run_simple` for more
            information.

        .. versionchanged:: 1.0
            If installed, python-dotenv will be used to load environment
            variables from :file:`.env` and :file:`.flaskenv` files.

            If set, the :envvar:`FLASK_ENV` and :envvar:`FLASK_DEBUG`
            environment variables will override :attr:`env` and
            :attr:`debug`.

            Threaded mode is enabled by default.

        .. versionchanged:: 0.10
            The default port is now picked from the ``SERVER_NAME``
            variable.
        """

 

三、调试模式 两种方式

# 方式一
from flask import Flask

# 生成一个flask对象
app = Flask(__name__)
# 设置成调试模式
app.debug = True

@app.route('/')
def index():
    return 'hhhhhh'

if __name__ == '__main__':
    # 对象加括号,调用哪个方法?  __call__
    app.run()
----------------------------------------------
# 方式二
from flask import Flask

# 生成一个flask对象
app = Flask(__name__)

@app.route('/')
def index():
    return 'hhhhhh'

if __name__ == '__main__':
    # 设置成调试模式
    app.run(debug=True)

注意 - 尽管交互式调试器在允许 fork 的环境中无法正常使用(也即在生产服务器上正常使用几乎是不可能的),但它依然允许执行任意代码。这使它成为一个巨大的安全隐患,因此它 绝对不能用于生产环境 。

screenshot of debugger in action
 运行中的调试器截图

四、url路由基本使用

@app.route('/')
def index():
    return 'Index Page'

@app.route('/hello')
def hello():
    return 'Hello World'

4-1 路由的变量规则

  • <variable_name>  - 标记特殊字段
  •  <converter:variable_name>  - 指定可选的转换器
@app.route('/user/<username>')
def show_user_profile(username):
    # show the user profile for that user
    return 'User %s' % username

@app.route('/post/<int:post_id>')
def show_post(post_id):
    # show the post with the given id, the id is an integer
    return 'Post %d' % post_id

转换器有下面几种

int 接受整数
float 同 int ,但是接受浮点数
path 和默认的相似,但也接受斜线

4-2 唯一 URL / 重定向行为

Flask 的 URL 规则基于 Werkzeug 的路由模块。这个模块背后的思想是基于 Apache 以及更早的 HTTP 服务器主张的先例,保证优雅且唯一的 URL。

@app.route('/projects/')
def projects():
    return 'The project page'

@app.route('/about')
def about():
    return 'The about page'

注意

虽然它们看起来着实相似,但它们结尾斜线的使用在 URL 定义 中不同。

  • 第一种情况中,指向 projects 的规范 URL 尾端有一个斜线。访问一个结尾不带斜线的 URL 会被 Flask 重定向到带斜线的规范 URL 去。
  • 第二种情况的 URL 结尾不带斜线,访问结尾带斜线的 URL 会产生一个 404 “Not Found” 错误。

这个行为使得在遗忘尾斜线时,允许关联的 URL 接任工作,与 Apache 和其它的服务器的行为并无二异。此外,也保证了 URL 的唯一,有助于避免搜索引擎索引同一个页面两次。

4-3 构造URL

如果 Flask 能匹配 URL,那么 Flask 可以生成它们吗?当然可以。

你可以用 url_for()来给指定的函数构造 URL。它接受函数名作为第一个参数,也接受对应 URL 规则的变量部分的命名参数。未知变量部分会添加到 URL 末尾作为查询参数。

>>> from flask import Flask, url_for
>>> app = Flask(__name__)
>>> @app.route('/')
... def index(): pass
...
>>> @app.route('/login')
... def login(): pass
...
>>> @app.route('/user/<username>')
... def profile(username): pass
...
>>> with app.test_request_context():
...  print url_for('index')
...  print url_for('login')
...  print url_for('login', next='/')
...  print url_for('profile', username='John Doe')
...
/
/login
/login?next=/
/user/John%20Doe

为什么你要构建 URL 而非在模板中硬编码?这里有三个绝妙的理由:

  1. 反向构建通常比硬编码的描述性更好。更重要的是,它允许你一次性修改 URL, 而不是到处边找边改。
  2. URL 构建会转义特殊字符和 Unicode 数据,免去你很多麻烦。
  3. 如果你的应用不位于 URL 的根路径(比如,在 /myapplication 下,而不是 / ), url_for() 会妥善处理这个问题。

五、HTTP方法

通过route内的methods参数,使路由回应指定请求。

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        do_the_login()
    else:
        show_the_login_form()

六、静态文件

 在你的包中或是模块的所在目录中创建一个名为 static 的文件夹,在应用中使用 /static 即可访问。

# 给静态文件生成 URL ,使用特殊的 'static' 端点名
# 这个文件应该存储在文件系统上的 static/style.css
url_for('static', filename='style.css')

七、模板渲染 - 基于jinja2模板引擎实现

from flask import render_template

@app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None):
    return render_template('hello.html', name=name)


'''
html页面 - 实现语言参考jinja2模板文档
'''
<!doctype html>
<title>Hello from Flask</title>
{% if name %}
  <h1>Hello {{ name }}!</h1>
{% else %}
  <h1>Hello World!</h1>
{% endif %}

注意:Flask 会在 templates 文件夹里寻找模板。

  • 如果你的应用是个模块,这个文件夹应该与模块同级
    /application.py
    /templates
        /hello.html
  • 如果它是一个包,那么这个文件夹作为包的子目录
    /application
        /__init__.py
        /templates
            /hello.html

八、请求数据访问

8-1 环境局部变量

理解其工作机制及如何利用环境局部变量实现自动化测试,否则可跳过。

Flask 中的某些对象是全局对象,但却不是通常的那种。这些对象实际上是特定环境的局部对象的代理。虽然很拗口,但实际上很容易理解。

想象一下处理线程的环境。一个请求传入,Web 服务器决定生成一个新线程( 或者别的什么东西,只要这个底层的对象可以胜任并发系统,而不仅仅是线程)。 当 Flask 开始它内部的请求处理时,它认定当前线程是活动的环境,并绑定当前的应用和 WSGI 环境到那个环境上(线程)。它的实现很巧妙,能保证一个应用调用另一个应用时不会出现问题。

所以,这对你来说意味着什么?除非你要做类似单元测试的东西,否则你基本上可以完全无视它。你会发现依赖于一段请求对象的代码,因没有请求对象无法正常运行。解决方案是,自行创建一个请求对象并且把它绑定到环境中。单元测试的最简单的解决方案是:用test_request_context() 环境管理器。结合 with 声明,绑定一个测试请求,这样你才能与之交互。

from flask import request

with app.test_request_context('/hello', method='POST'):
    # now you can do something with the request until the
    # end of the with block, such as basic assertions:
    assert request.path == '/hello'
    assert request.method == 'POST'

'''
另一种可能是:传递整个 WSGI 环境给 request_context() 方法
'''
from flask import request

with app.request_context(environ):
    assert request.method == 'POST'

8-2 Request对象

当前请求的 HTTP 方法可通过 method 属性来访问。

通过:attr:~flask.request.form 属性来访问表单数据( POST 或 PUT 请求提交的数据)。

from flask import request
@app.route('/login', methods=['POST', 'GET'])
def login():
    error = None
    if request.method == 'POST':
        if valid_login(request.form['username'],
                       request.form['password']):
            return log_the_user_in(request.form['username'])
        else:
            error = 'Invalid username/password'
    # the code below is executed if the request method
    # was GET or the credentials were invalid
    return render_template('login.html', error=error)

注意:当访问 form 属性中的不存在的键会发生什么?会抛出一个特殊的KeyError异常。

你可以像捕获标准的KeyError一样来捕获它。 如果你不这么做,它会显示一个 HTTP 400 Bad Request 错误页面。所以,多数情况下你并不需要干预这个行为。

8-2-1 args属性 - 访问URL提交的参数(/…?key=value)

searchword = request.args.get('q', '')

注意!!推荐用 get 来访问 URL 参数或捕获 KeyError ,因为用户可能会修改 URL,向他们展现一个 400 bad request 页面会影响用户体验。

九、文件上传

确保在 HTML 表单中设置enctype="multipart/form-data" 属性,不然你的浏览器根本不会发送文件。

已上传的文件存储在内存或是文件系统中一个临时的位置。

你可以通过请求对象的 files属性访问它们。每个上传的文件都会存储在这个字典里。它表现近乎为一个标准的 Python file 对象,但它还有一个 save()方法,这个方法允许你把文件保存到服务器的文件系统上

from flask import request

@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        f = request.files['the_file']
        f.save('/var/www/uploads/uploaded_file.txt')
    ...

9-1 filename属性 - 查看上传前文件在客户端的文件名

!!注意 !!! 永远不要信任filename属性获取的值 ,这个值是可以伪造的。如果你要把文件按客户端提供的文件名存储在服务器上,那么请把它传递给 Werkzeug 提供的 secure_filename() 函数:

from flask import request
from werkzeug import secure_filename

@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        f = request.files['the_file']
        f.save('/var/www/uploads/' + secure_filename(f.filename))
    ...

十、Cookies

  • cookies - 访问Cookies
    • 请求对象的cookies 属性是一个内容为客户端提交的所有 Cookies 的字典。如果你想使用会话,请不要直接使用 Cookies
    • 获取 cookies.get(' cookies’s name ')
    • from flask import request
      
      @app.route('/')
      def index():
          username = request.cookies.get('username')
          # use cookies.get(key) instead of cookies[key] to not get a
          # KeyError if the cookie is missing.
  • set_cookies - 设置Cookies
    from flask import make_response
    
    @app.route('/')
    def index():
        resp = make_response(render_template(...))
        resp.set_cookie('username', 'the username')
        return resp

    可注意到的是,Cookies 是设置在响应对象上的

  • 由于通常视图函数只是返回字符串,之后 Flask 将字符串转换为响应对象。如果你要显式地转换,你可以使用 make_response() 函数然后再进行修改。

    有时候你想设置 Cookie,但响应对象不能醋在。这可以利用 延迟请求回调 模式实现。

十一、重定向和错误 - redirect()、abort()

  • redirect() - 实现重定向
  • abort() - 放弃请求并返回错误代码
'''
这是一个相当无意义的例子因为用户会从主页重定向到一个不能访问的页面 (401 意味着禁止访问)
但是它展示了重定向是如何工作的。
'''

from flask import abort, redirect, url_for

@app.route('/')
def index():
    return redirect(url_for('login'))

@app.route('/login')
def login():
    abort(401)
    this_is_never_executed()

11- 1 errorhandler() 装饰器 - 定制错误页面

!!!注意  - render_template()调用之后的 404 。这告诉 Flask,该页的错误代码是 404 ,即没有找到。默认为 200,也就是一切正常。

from flask import render_template

@app.errorhandler(404)
def page_not_found(error):
    return render_template('page_not_found.html'), 404

十二、响应对象 make_response() - 操纵Flask把返回值转换为响应对象的逻辑

视图函数的返回值会被自动转换为一个响应对象。如果返回值是一个字符串, 它被转换为该字符串为主体的、状态码为 200 OK``的 、 MIME 类型是 ``text/html 的响应对象

Flask 把返回值转换为响应对象的逻辑

  1. 如果返回的是一个合法的响应对象,它会从视图直接返回。
  2. 如果返回的是一个字符串,响应对象会用字符串数据和默认参数创建。
  3. 如果返回的是一个元组,且元组中的元素可以提供额外的信息。这样的元组必须是 (response, status, headers) 的形式,且至少包含一个元素。 status 值会覆盖状态代码, headers 可以是一个列表或字典,作为额外的消息标头值。
  4. 如果上述条件均不满足, Flask 会假设返回值是一个合法的 WSGI 应用程序,并转换为一个请求对象。

如果你想在视图里操纵上述步骤结果的响应对象,可以使用 make_response()函数

@app.errorhandler(404)
def not_found(error):
    return render_template('error.html'), 404

# 你只需要把返回值表达式传递给 make_response() ,获取结果对象并修改,然后再返回它
@app.errorhandler(404)
def not_found(error):
    resp = make_response(render_template('error.html'), 404)
    resp.headers['X-Something'] = 'A value'
    return resp

十三、session对象

注意 : 要使用会话,需要设置一个密钥 - secret_key ,即加密时需要的盐

Flask 会将你放进会话对象的值序列化至 Cookies。如果你发现某些值在请求之间并没有持久存在,然而确实已经启用了 Cookies,但也没有得到明确的错误信息。这时,请检查你的页面响应中的 Cookies 的大小,并与 Web 浏览器所支持的大小对比。

from flask import Flask, session, redirect, url_for, escape, request

app = Flask(__name__)

# set the secret key.  keep this really secret:
app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'

@app.route('/')
def index():
    if 'username' in session:
        # escape() 可以在模板引擎外做转义
        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'))

十四、消息闪现

反馈,是良好的应用和用户界面的重要构成。如果用户得不到足够的反馈,他们很可能开始厌恶这个应用。 Flask 提供了消息闪现系统,可以简单地给用户反馈。 消息闪现系统通常会在请求结束时记录信息,并在下一个(且仅在下一个)请求中访问记录的信息。展现这些消息通常结合要模板布局。

使用 flash() 方法可以闪现一条消息。要操作消息本身,请使用 get_flashed_messages()函数,并且在模板中也可以使用。完整的例子见 消息闪现 部分。

十五、日志记录

有时候你会处于这样一种境地,你处理的数据本应该是正确的,但实际上不是。 比如,你会有一些向服务器发送请求的客户端代码,但请求显然是畸形的。这可能是用户篡改了数据,或是客户端代码的粗制滥造。大多数情况下,正常地返回 400 Bad Request 就可以了,但是有时候不能这么做,并且要让代码继续运行。

你可能依然想要记录下,是什么不对劲。这时日志记录就派上了用场。从 Flask 0.3 开始,Flask 就已经预置了日志系统。

app.logger.debug('A value for debugging')
app.logger.warning('A warning occurred (%d apples)', 42)
app.logger.error('An error occurred')

十六、整合WSGI中间件

如果你想给你的应用添加 WSGI 中间件,你可以封装内部 WSGI 应用。

# 用 Werkzeug 包中的某个中间件来应付 lighttpd 中的 bugs 
from werkzeug.contrib.fixers import LighttpdCGIRootFix
app.wsgi_app = LighttpdCGIRootFix(app.wsgi_app)

猜你喜欢

转载自blog.csdn.net/qq_33961117/article/details/87289192
今日推荐