看这篇文章之前,推荐先看一下我之前写的:flask中的路由匹配是如何实现的?BluePrint(蓝图)的概念简单来说就是一个路由组。所有注册到这个蓝图上的路由都使用相同的前缀。这样便于管理,不同的功能可以在一个模块(如admin模块)中实现,解耦性更强。首先我们看一下蓝图是如何使用的:#定义一个蓝图simple_page=Blueprint('simple_page',__name__,template_folder='templates')#绑定视图函数@simple_page.route('/',defaults={'page':'index'})@simple_page.route('/')defshow(page):try:returnrender_template('pages/%s.html'%page)exceptTemplateNotFound:abort(404)#在main模块中注册路由app=Flask(__name__)app.register_blueprint(simple_page)看上面的例子,先定义一个蓝图simple_page,然后通过这个蓝图定义路由并绑定到视图函数,最后在mainmodule,register这个蓝图就可以了。看起来和常见的定义视图函数的方式一样,只是在添加路由的时候需要从蓝图入手。我们来看看它在源码中是如何实现的。flask0.7中添加了蓝图功能。当应用程序调用register_blueprint方法时,会调用Blueprint类中的register方法来注册蓝图中添加的所有路由。defregister_blueprint(self,blueprint,**options):...blueprint.register(self,options,first_registration)我们来看看注册方法:#blueprints.pydefregister(self,app,options,first_registration=False):...state=self.make_setup_state(app,options,first_registration)...fordeferredinself.deferred_functions:deferred(state),什么是make_setup_state,什么是deferred_functions。让我们跳转到make_setup_state看看里面有什么:defmake_setup_state(self,app,options,first_registration=False):returnBlueprintSetupState(self,app,options,first_registration)返回一个类。没关系。让我们来看看deferred_functions是什么。从名字就可以看出是延迟函数之类的。我们梳理一下流程。app.register_blueprint注册蓝图后,会激活Buleprint类中的register方法。在register方法中,会调用deferred_functions中的函数执行。我们大概可以猜到,这段代码的作用就是为蓝图定义的路由添加到路由组中。以上面的蓝图为例,@simple_page.route('/',defaults={'page':'index'})蓝图的路由方法如下所示:defroute(self,rule,**options):defdecorator(f):self.add_url_rule(rule,f.__name__,f,**options)returnfreturndecoratorroute方法是一个装饰器,实际调用的是add_url_rule方法:defadd_url_rule(self,rule,endpoint=None,view_func=None,**options):self.record(lambdas:s.add_url_rule(rule,endpoint,view_func,**options))defrecord(self,func):....self.deferred_functions.append(func)在记录中方法,将func添加到deferred_functions列表中,调用add_url_rule中的record方法,那么一切就可以解释了:register方法中的这段代码,state=self.make_setup_state(app,options,first_registration)...fordeferredinself.deferred_functions:deferred(state)loopsdeferred_functions,deferred_functions里面有什么?它是拉姆达。具体来说就是蓝图中定义的路由和视图函数。我们通过@simple_page.route('/')定义路由后,实际上是在deferred_functions中添加了一个lambda。为什么叫defer,因为只有在register注册的时候才会加入到app的url_map中。上面代码中的state是BlueprintSetupState的一个例子。该类中有一个add_url_rule方法,会在全局app的url_map中添加路由和视图功能。defadd_url_rule(self,rule,endpoint=None,view_func=None,**options):self.app.add_url_rule(rule,'%s.%s'%(self.blueprint.name,endpoint),view_func,defaults=defaults,**options)整理一下:#state是BlueprintSetupState实例BlueprintSetupState->state#deferred_functions是蓝图路由的lambdalambdas:s.add_url_rule->deferred_functionsfordeferredinself.deferred_functions:deferred(state)表示lambdas被分配了状态,然后是state.add_url_rule,这样app.add_url_rule就被执行了。延迟执行的设计太巧妙了。蓝图中添加的路由规则只是在register方法中才真正添加到全局路由图中。我的博客:https://blog.shiniao.fun/