flask.__init__.py
和核心组件首先看看一个简单的示例。使用 Flask ,一般是从 flask 模块导入 Flask 、 request 等等组件。一个简单的示例以下:html
from flask import Flask app = Flask(__name__) app.config.update(DEBUG=True) @app.route('/') @app.route('/index') def index(): return '<h1>Hello, world!</h1>' if __name__ == '__main__': app.run()
这个简单示例只使用到 Flask 中的核心 Flask 对象,以及 Flask 的 route 机制,就能简单地提供一个显示 Hello, world!
字符串的 index 页面。其它更加复杂的结构和使用模式,都会基于相似的简单例子进行扩展,以知足一些特定场景的要求。web
flask.__init__.py
除了 Flask 类,在 flask 模块里面还包含了其它 Flask 里的核心组件,打开这个源文件,可看到它里面包括:redis
abort数据库
从 werkzeug.exceptions
导入,调用时直接抛出异常。它的本质是 werkzeug.exceptions
里面的 Aborter() 对象。编程
Aborter 使用工厂模式。其内部使用一个 dict 类型的 mapping
成员变量来保存从 http 状态码到 werkzeug.exceptions
中定义的全部异常类之间的一个映射,而后经过一个 magic 方法 __call__
建立并抛出异常。json
全部的异常的基类为 HTTPException
。它包含了两个基本的成员,code
和 description
,分别表示停止时的 http 状态码和要返回给用户的信息。flask
异常类定义完后,经过一个函数 _find_exceptions
把全部在这里定义的异常类,放入到 default_exceptions
这个 dict 全局变量中。Abort 的初始化函数默认用 default_exceptions
做为 mapping
的值。浏览器
abort
支持的状态码包括 400 / 401 / 403 / 404 / 405 / 406 / 408 / 409 / 410 / 411 / 412 / 413 / 414 / 415 / 416 / 417 / 418 / 422 / 428 / 429 / 429 / 431 / 500 / 501 / 502 / 503 / 504/ 505 。安全
使用示例:服务器
@app.route('/_404') def _404() abort(404, 'Oops, 404.')
redirect
从 werkzeug.utils
导入的重定向函数,一般与 url_for
结合使用。
redirect
生成一个 Response
对象,默认以 302 状态码返回响应。其响应的模板内容为(其中 escape 为 URL 转义函数):
'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">\n' '<title>Redirecting...</title>\n' '<h1>Redirecting...</h1>\n' '<p>You should be redirected automatically to target URL: ' '<a href="%s">%s</a>. If not click the link.' % (escape(location), display_location), code, mimetype='text/html'
可见,当浏览器不支持 302 状态码自动重定向时,可经过点击响应的 html 中的连接进行跳转。
使用示例:
@app.route('/_redirect') def _redirect() return redirect(url_for('.index'))
Markup 和 escape
这两个都是从 Jinja2
中导入,实际由另一个模块 markupsafe
实现。 Markup
在 markupsafe
模块的 __init__.py
中,是对文本的一个封装,对字符串进行安全的转义,从而能方便地使用到 html 和 xml 中。 Markup
的实现过程当中,使用到 escape
函数帮助转义。
escape
的实现其实很简单,就是把 html 中的预留字符转换为实体,代码以下:
return Markup(text_type(s) .replace('&', '&') .replace('>', '>') .replace('<', '<') .replace("'", ''') .replace('"', '"') )
就是把 & > < ' "
这几个字符转换为实体。
使用示例:
Markup('<h1>%s<h1>') % '<h1>Hello, world!<h1>' # 结果为 Markup('<h1><h1>Hello, world!<h1><h1>')
Flask Request Response
这 3 个类从 flask.app
中导入(使用了当前相对位置导入 from .app import ...
)。
Flask
是整个 Flask 框架的核心类,它实现了 WSGI 的应用接口,提供路由、模板解析、日志、异常管理等等核心功能。
Request
和 Response
分别是对请求和响应的数据的包装,实际的代码在 flask.wrappers
中。它们继承 werkzeug.wrappers
里面的请求和响应类,根据 Flask 的设计概念的须要进行了扩展。
后续深刻分析这 3 个类
使用示例:
from flask import Flask, Response, request app = Flask(__name__) @app.route('/') def index(): method = request.method return Response('Request method: %s' % method) if __name__ == '__main__': app.run()
辅助函数 url_for
flash
send_file
, send_from_directory
等
这堆辅助函数从 flask.helpers
中导入,包括:
url_for, flash, send_file, send_from_directory, get_flashed_messages, get_template_attribute, make_response, safe_join, stream_with_context
后续深刻分析这些函数
上下文全局对象代理 current_app
g
request
等
这些对象从 flask.globals
导入,在当前上下文环境中起做用,包括:
current_app, g, request, session, _request_ctx_stack, _app_ctx_stack
上下文模式是 web 框架中常常会使用到的模式,它表示当前会话、请求、应用的执行环境,是当前代码执行时所能使用到的变量、函数等等。不一样的用户一般使用不一样的上下文环境,经过相互隔离上下文环境提供必定的安全特性。上下文还与特定的实现技术有关,线程、协程会使用不一样的实现方法,有时在不一样的系统中会有须要注意的细节。
在实践中遇到的一些问题,特别是与 Flask 扩展有关的问题,不少是与上下文不对有关。
注意,current_app
g
request
session
均是 LocalProxy
,在运行时经过查找函数加载真正的对象。
后续深刻分析 flask.globals
。
上下文处理 has_request_context
has_app_context
after_this_request
copy_current_request_context
这些函数和组件从 flask.ctx
导入,辅助处理上下文。
在 flask.ctx
中还定义了 ApplcaitonContext
和 RequestContext
两个上下文类。
RequestContext
包含请求时的信息,在请求开始时建立,在请求结束后清理。
ApplicationContext
包含应用的信息,绑定到当前的线程和协程上。当 RequestContext
发现没有 ApplicationContext
时,也会自动隐式建立一个(在 RequestContext.push()
中)。
后续深刻分析。
Module 和 Blueprint
分别从 flask.module
和 flask.blueprints
导入,是 Flask 的扩展机制。根据 Module
中的注释,这种方式已通过时,被 Blueprint
取代。
.. versionchanged:: 0.7 Modules were deprecated in favor for blueprints.
Blueprint
是 Flask 中的主要模块化扩展方法。在编写大规模的应用时,可划分功能为多个 Blueprint
,每一个 Blueprint
完成特定任务。
使用示例:
task_bp = Blueprint('task') app.register_blueprint(task_bp, url_prefix='/task')
后续深刻分析。
视图渲染 render_template
render_template_string
这两个函数从 flask.templating
导入,完成模板的渲染工做。
使用示例:
# 模板文件 templates/index.html <h1>{{ content }}</h1> # 视图渲染代码 @app.route('/') def index(): return render_template('index.html', content='Hello, world!')
后续深刻分析。
内部信号 signals_available
template_rendered
request_started
等等
Flask 提供信号机制,当某些操做发生时,经过信号方式通知其它代码,方便在这些操做发生时进行进一步处理。
现有的信号包括:
signals_available, template_rendered, request_started, request_finished, got_request_exception, request_tearing_down, appcontext_tearing_down, appcontext_pushed, appcontext_popped, message_flashed
信号机制使用 blinker ,若是要自定义信号,须要额外安装这个模块。
json 支持 jsonify
经过 json 方式进行响应。
使用示例:
return jsonify([1,2,3,4])
Session
Session 对象,实际类型为 'flask.sessions.SecureCookieSession',须要结合 SecureCookieSessionInterface
一块儿使用。
它能够用来定制 Flask 的 Session 保存方式,可放入到数据库或者 redis 里面,实现跨服务器的 session 共享。session 共享后,可经过服务器集群提高整个应用的访问处理能力。
官方文档有一个使用 redis 实现的 server-side session http://flask.pocoo.org/snippets/75/ 。
后续深刻分析。
以上已列出 Flask 里面的关键组件和概念,若是掌握这部分的概念,则使用 Flask 的过程当中所遇到的问题基本能本身动手调试和解决。刚接触像上下文、信号机制、server-side session 等概念时会存在疑惑,这些概念须要理解源代码后,实际编程使用的过程当中会慢慢熟悉。
后续的文章围绕上述概念展开,并探索 Flask 如何设计和实现这些概念,在整个实现过程当中学习 Flask 的优秀设计。