Flask Http请求 - 上下文 、请求钩子

基础知识

Flask有两个主要依赖

  1. WSGI(Web Server Gateway Interface,Web服务器网关接口)工具集——Werkzeug
  • WSGI(Web Server Gateway Interface)是Python中用来规定Web服务器如何与Python Web程序进行沟通的标准
  • Werkzeug实现路由、调试和Web服务器网关接口
  1. Jinja2模板引擎
  • Jinja2负责Html Template

Flask HTTP请求

请求处理流程

  1. 用户在浏览器输入URL访问某个资源。
  2. Flask通过WSGI将HTTP的请求转换解释成Python内容
  3. Flask根据请求的URL执行对应的视图函数,获取返回值生成响应
  4. 响应依次经过WSGI转换生成HTTP响应,再经由Web服务器传递给浏览器
  5. 浏览器接收并解析响应,将信息显示在页面中。

Flask Http请求 - 上下文 、请求钩子

Flask上下文

Flask中上下文有两种

  • 请求上下文

请求上下文包含

  1. request : flask将请求信息都包装在request对象中,包含Url,请求方法,Header,请求参数等内容,可以直接在视图函数中获取
  2. session 
  • 应用上下文

应用上下文包含

  1. current_app : 请求当前的应用实例,包含配置信息等
  2. 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,具体步骤大致如下:
  1. 防止之前的请求有异常没有正常终止,先将在最上面的请求上下文pop出来
  2. 如果缺少应用上下文,先创建一个
  3. 先后push应用上下文和请求上下文到分别对应的stack中
  4. 打开session
  5. 通过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 :在视图函数内注册,只会在该视图函数后执行

Flask Http请求 - 上下文 、请求钩子

上一篇:如何将模型可视化工具Netron改造为通用的WEB服务(Flask)?


下一篇:Ubuntu18.04 显卡驱动安装(解决各种疑难杂症)