Flask源码解读


一:Flask 整体框架图

下面是我画的一个Flask整体框架图,大家可以对照着这个图来阅读下边的源码解读。

在这里插入图片描述

二:route源码分析

route装饰器在app.py的Flask类中,它完成了路由的注册和视图函数的注册。

阅读 route源码之前我们先看看了解flask中,构建路由规则的两种方法:

  1. 通过 @app.route()
  2. 通过 app.add_url_rule,这个方法的签名为 add_url_rule(self,
    rule, endpoint=None, view_func=None, **options),参数的含义如下:
    (1) rule:url 规则字符串,可以是静态的 /path,也可以包含 /
    (2) endpoint:要注册规则的endpoint,默认是 view_func 的名字
    (3) view_func:对应 url 的处理函数,也被称为视图函数

这两种方法是等价的也就是说:

@app.route('/')
def hello():
	return ''hello,world ! ''

也可以写成

def hello():
	return "helo world ! "

app.add_url_rule('/', 'hello', hello)

下面我们来看 route 方法,为了方便阅读我删除了其中的注释部分上边为源码,下边为解读:


def route(self, rule, **options):
    
    def decorator(f):
        endpoint = options.pop("endpoint", None)
        self.add_url_rule(rule, endpoint, f, **options)
        return f

    return decorator

通过装饰器将url传入到add_url_rule当中的rule,methods以**options关键字参数传入到add_url_rule中,这也验证了上面两种方法等价的说法。


def add_url_rule(
        self,
        rule,
        endpoint=None,
        view_func=None,
        provide_automatic_options=None,
        **options
):
    if endpoint is None:
        endpoint = _endpoint_from_view_func(view_func)
    options["endpoint"] = endpoint
    methods = options.pop("methods", None)

在add_url_rule中,判断endpoint是否为空,为空调用_endpoint_from_view_func函数从视图函数中以字符串取出视图函数名,并将endpoint添加到字典options当中


def _endpoint_from_view_func(view_func):
    assert view_func is not None, "expected view func if endpoint is not provided."
    return view_func.__name__

_endpoint_from_view_func函数返回视图函数的__name__属性


if methods is None:
    methods = getattr(view_func, "methods", None) or ("GET",)       #提取属性,有过没有mnethods属性就给他一个GET

if provide_automatic_options is None:
    if "OPTIONS" not in methods:
        provide_automatic_options = True
        required_methods.add("OPTIONS")
    else:
        provide_automatic_options = False

methods |= required_methods                                          #连接字典结果放在methods中

这块是构建 methods 的部分逻辑,有几个python的知识点我给注释了


rule = self.url_rule_class(rule, methods=methods, **options)
rule.provide_automatic_options = provide_automatic_options

self.url_map.add(rule)

self.url_rule_class我们跟进去会发现他就是routing.py下的Rule类。所以此处是将rule、methods、**options传入Rule类构造出一个rule对象,将该rule对象添加到url_map当中.其中 options[‘endpoint’]=endpoint, rule=url . 通过routing.py的Rule类建立了(url,endpoint,methods)的映射关系


self.url_map = self.url_map_class()  
url_map_class = Map

上边两步是我们跟url_map的过程,url_map是routing.py的Map类创建出来的一个对象,用来存储Rule的对象


url_map = Map([
	Rule('/',endpoint=/index/),
	Rule('static',endpoint='static'
	])

如上Map内是用列表来存储Rule的对象


if view_func is not None:
    old_func = self.view_functions.get(endpoint)
    if old_func is not None and old_func != view_func:
        raise AssertionError(
            "View function mapping is overwriting an "
            "existing endpoint function: %s" % endpoint
        )
    self.view_functions[endpoint] = view_func

上面这段代码主要做的事情就是更新 self.url_map 和 self.view_functions 两个变量。

系统梳理:

add_url_rule的view_func就是app.route构造器修饰的视图函数,

app.py的Flask类定义了view_functions为一个空字典,存储了所有的{endpoint:view_func}映射关系;

Flask的url_map存储了所有的(url,endpoint)映射关系;

至此,url与视图函数就通过endpoint映射起来了,请求时服务器对请求进行转发,解析得到url,通过MapAdapter类的match方法得到endpoint,再通过view_functions找到对应的视图函数,直接调用函数执行,就完成了一个完整的route

三:请求到响应源码

我们通过一个实例引入:


from flask import Flask

app = Flask(__name__)

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

    return 'Hello World!'

就这样flask实例就生成了

但是当调用app的时候,实际上调用了Flask的__call__方法, 这就是app工作的开始

Flask的__call__源码如下:


def __call__(self
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值