基础知识
Flask有两个主要依赖
- WSGI(Web Server Gateway Interface,Web服务器网关接口)工具集——Werkzeug
- WSGI(Web Server Gateway Interface)是Python中用来规定Web服务器如何与Python Web程序进行沟通的标准
- Werkzeug实现路由、调试和Web服务器网关接口
- Jinja2负责Html Template
Flask HTTP请求
请求处理流程
- 用户在浏览器输入URL访问某个资源。
- Flask通过WSGI将HTTP的请求转换解释成Python内容
- Flask根据请求的URL执行对应的视图函数,获取返回值生成响应
- 响应依次经过WSGI转换生成HTTP响应,再经由Web服务器传递给浏览器
- 浏览器接收并解析响应,将信息显示在页面中。
Flask上下文
Flask中上下文有两种
- 请求上下文
请求上下文包含
- request : flask将请求信息都包装在request对象中,包含Url,请求方法,Header,请求参数等内容,可以直接在视图函数中获取
- session
- 应用上下文
应用上下文包含
- current_app : 请求当前的应用实例,包含配置信息等
- g : 应用上下文会随着每次请求的进入激活,每次请求的结束会销毁,所以g仅在当前的请求中可用,通常会搭配before_request钩子使用
以下实例展示
@app.before_request
def set_name():
g.name = 'my_name'
@app.route("/")
def hello_world():
print(request.url)
print(request.method)
session["USERNAME"] = "test"
print(session)
print(current_app.secret_key)
print(g.get('name'))
return "<p>Hello, World!</p>"
访问http://127.0.0.1:5000/ ,输出结果如下
http://127.0.0.1:5000/
GET
<SecureCookieSession {'USERNAME': 'test'}>
miles-secret
my_name
Flask 上下文如何工作
- 请求上下文和应用上下文以堆的形式存储,分别为_request_ctx_stack以及_app_ctx_stack
- Flask通过Flask.wsgi_app()方法管理上下文,Flask在每个请求后创建当前请求上下文
- 创建当前的请求上下文后,通过Flask.push()方法,分别push到_request_ctx_stack和_app_ctx_stack,具体步骤大致如下:
- 防止之前的请求有异常没有正常终止,先将在最上面的请求上下文pop出来
- 如果缺少应用上下文,先创建一个
- 先后push应用上下文和请求上下文到分别对应的stack中
- 打开session
- 通过url匹配视图
flask.push()方法源码
def push(self) -> None:
"""Binds the request context to the current context."""
# If an exception occurs in debug mode or if context preservation is
# activated under exception situations exactly one context stays
# on the stack. The rationale is that you want to access that
# information under debug situations. However if someone forgets to
# pop that context again we want to make sure that on the next push
# it's invalidated, otherwise we run at risk that something leaks
# memory. This is usually only a problem in test suite since this
# functionality is not active in production environments.
top = _request_ctx_stack.top
if top is not None and top.preserved:
top.pop(top._preserved_exc)
# Before we push the request context we have to ensure that there
# is an application context.
app_ctx = _app_ctx_stack.top
if app_ctx is None or app_ctx.app != self.app:
app_ctx = self.app.app_context()
app_ctx.push()
self._implicit_app_ctx_stack.append(app_ctx)
else:
self._implicit_app_ctx_stack.append(None)
_request_ctx_stack.push(self)
# Open the session at the moment that the request context is available.
# This allows a custom open_session method to use the request context.
# Only open a new session if this is the first time the request was
# pushed, otherwise stream_with_context loses the session.
if self.session is None:
session_interface = self.app.session_interface
self.session = session_interface.open_session(self.app, self.request)
if self.session is None:
self.session = session_interface.make_null_session(self.app)
# Match the request URL after loading the session, so that the
# session is available in custom URL converters.
if self.url_adapter is not None:
self.match_request()
Flask请求钩子
通过请求钩子(Hook),可以注在不同的请求处理阶段执行不同的函数,对请求进行预处理和后处理工作,比如处理数据库连接,打印日志等。
Flask请求钩子包括:
- before_ first_request : 在第一个请求前运行
- before_request : 在每个请求前运行
- after_request:在每个请求后运行,前提-没有抛出异常
- teardown_request:在每个请求后运行,与after_request不同的是即使有异常抛出仍会执行,如果有异常,会传入异常对象作为参数
- after_this_request :在视图函数内注册,只会在该视图函数后执行