Flask框架知识系列之四

时间:2022-06-10 12:59:59

1,蓝图定义:

Flask 用 蓝图(blueprints) 的概念来在一个应用中或跨应用制作应用组件和支持通用的模式。
蓝图很好地简化了大型应用工作的方式,并提供给 Flask 扩展在应用上注册操作的核心方法。
一个 Blueprint 对象与 Flask 应用对象的工作方式很像,但它确实不是一个应用,而是一个描述如何构建或扩展应用的 蓝图 。

以上官方说法,太抽象,看以下解释:

蓝图 /Blueprint 是Flask应用程序 组件化 的方法,可以在一个应用内或跨越 多个项目共用蓝图。
使用蓝图可以极大地简化大型应用的开发难度,也为Flask扩展 提供了一种在应用中注册服务的集中式机制。

2,蓝图的应用场景

1,把一个应用分解为一个蓝图的集合。这对大型应用是理想的。一个项目可以实例化一个应用对象,初始化几个扩展,并注册一集合的蓝图。

2,以 URL 前缀和/或子域名,在应用上注册一个蓝图。 URL 前缀/子域名中的参数即成为这个蓝图下的所有视图函数的共同的视图参数(默认情况下)。

3,在一个应用中用不同的 URL 规则多次注册一个蓝图。

4,通过蓝图提供模板过滤器、静态文件、模板和其它功能。一个蓝图不一定要实现应用或者视图函数。

5,初始化一个 Flask 扩展时,在这些情况中注册一个蓝图。

Flask 中的蓝图不是即插应用,因为它实际上并不是一个应用——它是可以注册,甚至可以多次注册到应用上的操作集合。

蓝图对象没有办法独立运行,必须将它注册到一个应用对象上才能生效。

蓝图作为 Flask 层提供分割的替代,共享应用配置,并且在必要情况下可以更改所注册的应用对象

3,蓝图的缺点

它的缺点是你不能在应用创建后撤销注册一个蓝图而不销毁整个应用对象。
上面这句话我的理解是如下,不知对不对(很纠结):
如果在应用创建后,你撤销注册一个蓝图,那么就必须销毁整个应用对象。

4,使用蓝图的三个步骤

1.创建 一个蓝图对象
blue = Blueprint("blue",__name__)

2.在这个蓝图对象上进行 操作 ,例如注册路由、指定静态文件夹、注册模板过滤器...
@blue.route('/')
def blue_index():
return 'Welcome to my blueprint'

3.在应用对象上 注册 这个蓝图对象
app.register_blueprint(blue,url_prefix='/blue')

5,蓝图的运行机制–说白了就是会自动补充URL前缀,并且能使用相同的视图函数

蓝图并不是一个可插拔的应用 —— 它只是保存了一组 将来 可以在应用对象上执行 的 操作 —— 注册路由就是一种操作。

当在应用对象上调用 route 装饰器或使用 add_url_rule()方法 注册路由时, 我们已经知道,这个操作将修改应用对象的两张路由表:url_map和view_functions;

然而,蓝图对象根本就没有路由表,当我们在蓝图对象上调用route装饰器或使用 add_url_rule()方法注册路由时,它只是在内部的一个延迟操作记录列表 defered_functions 中添加了一项:

下图为blueprint和Flask route的对比:

Flask框架知识系列之四

lambad s: s.add_url_rule(‘/’,view_func=ezbp_index)定义了一个匿名函数, 参数s就是将来被传入的应用对象。

当执行应用对象的 register_blueprint() 方法时,应用对象将从蓝图对象的 defered_functions 列表中取出每一项,并以自身 作为参数执行该匿名函数 —— 即调用应用对象的 add_url_rule() 方法,这将真正的 修改应用对象的两张路由表。

所以说,蓝图这个名字起得的确恰当,蓝图的那些方法仅仅记录了未来应该发生的操作, 而不是当即实现。

蓝图的URL前缀

继续使用上面的图,注意其中被橘黄色荧光笔涂抹的代码:

当我们在应用对象上注册一个蓝图时,需要指定一个url_prefix关键字 参数(这个参数默认是/)。
在上面的图中可以看到,在应用最终的路由表 url_map中,在蓝图上注册的路由URL自动被加上了这个前缀。

这相当有用,我们可以在多个蓝图中使用相同的URL规则而不会最终引起冲突,
只要在 注册蓝图时将不同的蓝图挂接到不同的自路径即可 —— 想一想对于大型应用而言,不同 的蓝图通常是不同的人员开发的,你很难保证URL规则不发生冲突!

6,蓝图的endpoint–加上蓝图前缀

图继续,这次关注绿色荧光笔涂抹的代码:

我们创建蓝图对象时,第一个参数指定了蓝图的名字。当在应用中注册蓝图时, 蓝图的路由项中的访问点endpoint被自动添加了这个名字。

这有什么用?这涉及到 url_for() 的正确工作与否。

当不同的团队开发不同的蓝图时,和URL规则类似,你很难保证他们的视图函数名 彼此不同,尤其像index这样俗套的名字。如果不对来自不同蓝图的endpoint 进行区隔,那么 url_for(‘index’) 到底应该生成那个URL?这显然无法确定。

一旦给不同蓝图的endpoint加上了蓝图名前缀,我们可以确切地告诉url_for() 了:
url_for(‘shop.v_index’) # /shop/
url_for(‘admin.v_index’) # /admin/

7,注册静态目录路由

和应用对象不同,蓝图对象创建时不会默认注册静态目录的路由。
需要我们在 创建时指定 static_folder 参数。

下面的示例将蓝图所在目录下的 ezstatic目录设置为静态目录:

admin = Blueprint("admin",__name__,static_folder='ezstatic')
app.register_blueprint(admin,url_prefix='/admin')

默认情况下Flask使用文件夹的名称注册静态文件夹的路由:

Flask框架知识系列之四

现在就可以使用 /admin/ezstatic/ 访问mystatic目录下的静态文件了。

定制静态目录URL规则 :可以在创建蓝图对象时使用 static_url_path 来改变静态 目录的路由。下面的示例将为ezstatic文件夹的路由设置为 /lib:

admin = Blueprint("admin",__name__,static_folder='ezstatic',static_url_path='/lib')
app.register_blueprint(admin,url_prefix='/admin')

这时的路由表如下:

Flask框架知识系列之四

这样我们可以使用地址/admin/lib/main.css访问ezstatic目录下的main.css文件了

8,设置模板目录

蓝图对象没有默认的模板目录,可以在创建蓝图对象时使用 template_folder 关键字参数设置模板目录。
下面的示例将蓝图目录下的 mytpls 目录设置为模板目录:

admin = Blueprint('admin',__name__,template_folder='mytpls')

9,使用蓝图循环导入的问题

from flask import Blueprint
api = Blueprint('api', __name__)
from . import view

这边解释一下,首先定义一个蓝图,这个不用讲了,你用之前,肯定要定义一下吧,蓝图名字就叫api。

下面一行代码有点意思,from . import view, 这个代码,我发现用蓝图的人,很多都忘写了。

如果你是一个python老手,你应该知道,导入python文件,其实就是运行导入的那个文件。

在这边,你导入一次,就是告诉上级,这边还有个view.py文件,里面覆盖了一些接口。

整个根(run.py)就知道,哦,如果有接口访问这,我就指向你这边。

10,参考如下文章:

http://docs.jinkan.org/docs/flask/blueprints.html
http://www.cnblogs.com/fuzzier/p/6078761.html
http://www.cnblogs.com/yueerwanwan0204/p/5522749.html