Flask快速入门(11) — 请求流程

目录

  • full_dispatch_request()

flask项目整个请求流程其实就是执行:wsgi_app()方法中调用的full_dispatch_request(),包括请求扩展和真正的视图函数

full_dispatch_request()

def full_dispatch_request(self):
    # 执行before_first_request函数
    self.try_trigger_before_first_request_functions()
    try:
        # 发送请求开始信号
        request_started.send(self)
        # 执行请求之前函数
        rv = self.preprocess_request()
        # 如果请求之前函数没有返回值,执行请求函数
        if rv is None:
            rv = self.dispatch_request()
    except Exception as e:
        rv = self.handle_user_exception(e)
    # 执行请求之后函数
    return self.finalize_request(rv)

在分析这段代码之前,先回顾下请求扩展函数

(1)@app.before_first_request:就是将第一次请求之前的函数刚入self.before_first_request_funcs列表中

def before_first_request(self, f):
    self.before_first_request_funcs.append(f)
    return f

(2)@before_request:将请求之前函数放入self.before_request_funcs列表中

def before_request(self, f):
    self.before_request_funcs.setdefault(None, []).append(f)
    return f

(3)@after_request:将请求之后函数放在self.after_request_funcs列表中

def after_request(self, f):
    self.after_request_funcs.setdefault(None, []).append(f)
    return f

1. try_trigger_before_first_request_functions():第一次请求之前

def try_trigger_before_first_request_functions(self):
    if self._got_first_request:  # 初始为False
        return
    with self._before_request_lock:
        if self._got_first_request:
            return
        for func in self.before_first_request_funcs:
            func()
        self._got_first_request = True

将self.before_first_request_funcs也就是第一次请求前函数一个个取出执行。执行完后将self._got_first_request设为True。这样在后面的请求中就不再执行,也就是说只在第一次请求之前执行

2. self.preprocess_request():请求之前

def preprocess_request(self):
    bp = _request_ctx_stack.top.request.blueprint

    funcs = self.url_value_preprocessors.get(None, ())
    if bp is not None and bp in self.url_value_preprocessors:
        funcs = chain(funcs, self.url_value_preprocessors[bp])
    for func in funcs:
        func(request.endpoint, request.view_args)

    funcs = self.before_request_funcs.get(None, ())
    if bp is not None and bp in self.before_request_funcs:
        funcs = chain(funcs, self.before_request_funcs[bp])
    # 将请求之前函数遍历取出执行
    for func in funcs:
        rv = func()
        # 如果请求之前函数有返回值,则返回,下面的请求之前函数不再执行
        if rv is not None:
            return rv

3. self.dispatch_request():请求

def dispatch_request(self):
    req = _request_ctx_stack.top.request
    if req.routing_exception is not None:
        self.raise_routing_exception(req)
    rule = req.url_rule
    if (
        getattr(rule, "provide_automatic_options", False)
        and req.method == "OPTIONS"
    ):
        return self.make_default_options_response()
    # 执行真正的视图函数
    return self.view_functions[rule.endpoint](**req.view_args)

4. finalize_request():请求之后

def finalize_request(self, rv, from_error_handler=False):
    # 先make_response响应
    response = self.make_response(rv)
    try:
        # 执行请求之后函数
        response = self.process_response(response)
        # 发送请求结束信号
        request_finished.send(self, response=response)
    except Exception:
        if not from_error_handler:
            raise
        self.logger.exception(
            "Request finalizing failed with an error while handling an error"
        )
    # 将响应返回
    return response

def process_response(self, response):
    ctx = _request_ctx_stack.top
    bp = ctx.request.blueprin
    funcs = ctx._after_request_functions
    # reversed将请求之后函数列表进行了反转
    if bp is not None and bp in self.after_request_funcs:
        funcs = chain(funcs, reversed(self.after_request_funcs[bp]))
    if None in self.after_request_funcs:
        funcs = chain(funcs, reversed(self.after_request_funcs[None]))
    # 便利执行反转后的函数列表中的请求之后函数
    for handler in funcs:
        # 注意参数中有个response,所以我们的请求之后函数必须要有个参数。并且要有返回值
        response = handler(response)
    if not self.session_interface.is_null_session(ctx.session):
        self.session_interface.save_session(self, ctx.session, response)
    return response

以上就是请求相关的流程。总结:

  • 先执行第一次请求之前函数,执行完之后后续请求中不再执行
  • 再从上往下执行请求之前函数,如果有返回值,不再执行后面的请求之前函数,也不执行真正的视图函数
  • 没有返回值时执行视图函数,再执行请求之后函数
  • 请求之后函数必须要有参数,并且有返回值
  • 请求之后函数是从下往上返回执行

原文地址:https://www.cnblogs.com/863652104kai/p/11687747.html

时间: 2024-10-08 17:32:43

Flask快速入门(11) — 请求流程的相关文章

Flask快速入门(13) — 请求上下文1

目录 1. ctx=self.request_context(environ) 2. ctx.push() 2.1 _request_ctx_stack是什么? 3. response = self.full_dispatch_request() 4. ctx.auto_pop(error) 4.1 rv =_request_ctx_stack.pop() 之前分析了flask项目从启动到请求结束实际是执行了wsgi_app函数,在"请求流程"中也分析了self.full_dispat

Flask快速入门(15) — 请求上下文总结

目录 全局的变量 项目请求流程 全局的变量 _request_ctx_stack = LocalStack() _app_ctx_stack = LocalStack() current_app = LocalProxy(_find_app) #local就是我们的partial(_lookup_req_object, "request") request = LocalProxy(partial(_lookup_req_object, "request")) se

Flask快速入门(18) — 信号

Flask快速入门(18) - 信号 作用:Flask框架中的信号基于blinker,其主要就是让开发者可以在flask请求过程中定制一些用户行为 安装:pip install blinker 内置信号: request_started = _signals.signal('request-started') # 请求到来前执行 request_finished = _signals.signal('request-finished') # 请求结束后执行 before_render_templ

网站后端_Python+Flask.0003.FLASK快速入门之Hello Word?

框架特点: 1. 非常小, 小到可称为微型框架 2. 可扩展, 设计初衷就是不会替开发者做太多决策,支持随时更换或动手实现扩展模块 3. 三依赖, 路由/调试/WSGI(由WERKZEUG提供的WEB服务器网关接口实现),模版系统(由JINJA2实现),签名(由ITSDANGEROUS实现) 快速安装: pip install flask 快速入门: #!/usr/bin/env python # -*- coding: utf-8 -*- """ # # Authors: 

Flask快速入门(17) — flask_session

Flask快速入门(17) - flask_session 作用:将默认保存的签名cookie中的值,保存到 redis/memcached/file/Mongodb/SQLAlchemy 安装:pip install flask-session 使用1: from flask import Flask,session from flask_session import RedisSessionInterface import redis app = Flask(__name__) conn=r

Flask快速入门(20) — 多app应用

Flask快速入门(20) - 多app应用 之前一直是一个app,如果有多个app该怎么进行分发呢? from werkzeug.wsgi import DispatcherMiddleware from werkzeug.serving import run_simple from flask import Flask,current_app # 注册两个app app1 = Flask('app01') app2 = Flask('app02') @app1.route('/index')

【转】Flask快速入门

迫不及待要开始了吗?本页提供了一个很好的 Flask 介绍,并假定你已经安装好了 Flask.如果没有,请跳转到 安装 章节. 一个最小的应用 一个最小的 Flask 应用看起来会是这样: from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello World!' if __name__ == '__main__': app.run() 把它保存为 hello.py 

Flask快速入门,知识整理

一.Flask介绍(轻量级的框架,非常快速的就能把程序搭建起来) Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后触发Flask框架,开发人员基于Flask框架提供的功能对请求进行相应的处理,并返回给用户,如果要返回给用户复杂的内容时,需要借助jinja2模板来实现对模板的处理,即:将模板和数据进行渲染,将渲染后的字符串返回给用户浏览器. “微”

flask快速入门笔记三_上下文对象:Flask核心机制

首先声明:内容大部分来自huizhiwang,只是单纯记笔记. 1 请求 :WSGI WSGI,全称 Web Server Gateway Interface,或者 Python Web Server Gateway Interface ,是为 Python 语言定义的Web服务器和Web应用程序之间的一种简单而通用的接口. WSGI将Web服务分成两个部分:服务器和应用程序.WGSI服务器只负责与网络相关的两件事:接收浏览器的 HTTP请求.向浏览器发送HTTP应答:而对HTTP请求的具体处理