一、写在前面
有关Flask Blueprint的教程已经有很多了,光是CSDN上面的博客就已经有几十篇博客记录蓝图的使用方法。不过笔者一路走来,跟着前人的博客学习,一路跌跌撞撞踩了不少坑,这里想将所学的内容、项目中的实战经验进行总结,旨在提供一份清晰的、高效的Blueprint学习方案,给后面的学习者阅读。
二、蓝图的概念
【Core】从需求的角度解释什么是蓝图
Python Flask框架非常容易上手,短短几句话就能搭建起网页的后端,但是随着业务的变多,网页路由也变多,如果所有路由都挤到 app.py
里面,未免让维护人员难以招架,降低维护效率。
为了对路由做出分类管理,方便高效查询单元位置,Flask框架自带的蓝图
特性能够很好地解决这个问题。
我们可以通过两份不同的 app.py
来了解蓝图充当的作用:
图一:左图为不使用蓝图管理,右图使用蓝图管理 图一:左图为不使用蓝图管理,右图使用蓝图管理 图一:左图为不使用蓝图管理,右图使用蓝图管理
看到这份对比图,想必应该明了蓝图的作用了。
【Detail】蓝图的使用步骤
- 在路由管理中创建蓝图对象
- 通过包管理导入蓝图对象,便于上层提取
- 在
app.py
中导入蓝图对象,并完成注册
简单的三步,在实现过程中还有不少细节,我们一一解读:
三、从实战来讲解如何应用蓝图
下面讲解中用到的代码以及工程结构,来自于笔者目前开发的Flask部署深度学习模型的可视化项目,希望直接从实战中,带领各位了解蓝图的应用,冗长的文字描述,有助于新手阅读和理解。
0. 文件结构
图二:项目基本文件结构 图二:项目基本文件结构 图二:项目基本文件结构
如图所示是一个基本的Flask项目文件结构,分别有三个文件夹和一份python文件:
router
负责路由管理,也就是我们所用到的蓝图static
用于存放静态文件,例如css, js文件之类templates
用于存放html文件app.py
最外层唯一的python文件,也是用于执行的flask核心组织脚本
如果把router文件夹展开,会是这样一种结构:
图三: r o u t e r 文件夹的结构 图三:router文件夹的结构 图三:router文件夹的结构
我们设计router的核心理念,是将router视为一个python包来使用。
所以无论是router文件夹还是下面的每一个单元,都会有一份__init__.py
文件,这份__init__.py
在后面也会有作用。
1. 创建视图函数,并且创建蓝图对象
这里,我们以index
路径为例,该路由主要负责处理一些首页相关的基本页面交互功能。
我们首先新建一份index_view.py
文件,也被称作视图函数,以便管理我们的路由。
注意起名规则:一般以name_view.py来命名视图函数
视图函数中的内容如下图:
图四:视图函数中的内容 图四:视图函数中的内容 图四:视图函数中的内容
从上面的代码中,我们可以获取如下信息:
- 首先,创建蓝图对象。
index_bp = Blueprint('index', __name__)
这句话就是在创建蓝图对象,第一个参数是蓝图的名字,第二个参数是表示:以这份.py文件作为视图函数 - 进行路由的创建。创建路由有统一格式,从原来的
app.route()
, 变成了index_bp.route()
,也就是您刚刚创建的蓝图对象,替换原来的app
,在括号中输入自己定义的路由。
2 【非常重要】记得导出蓝图对象
这个导出蓝图对象是层层导出的关系。
核心目标就是能让最外层的app.py
能够使用到这里的index_bp
。
所以,在index
路径下的__init__.py
中,有:
from .index_view import index_bp
一句话即可,达成引入index_bp
对象的目的。
在router
路径下的__init__.py
中,有:
from .index import index_bp
这句代码的意思是,从该目录下的index
包中,引入index_bp
对象。
当然,考虑到还有另外两份路由,最终的router.__init__.py
是这样的:
from .index import index_bp
from .paper import paper_bp
from .process import process_bp
3. 在app.py
中完成蓝图的注册
以下是app.py
的代码:
from flask import Flask
from datetime import timedelta
from router import index_bp, paper_bp, process_bp
app = Flask(__name__)
app.secret_key = 'secret!'
app.config['SEND_FILE_MAX_AGE_DEFAULT'] = timedelta(seconds=1)
app.register_blueprint(index_bp)
app.register_blueprint(paper_bp, url_prefix='/paper')
app.register_blueprint(process_bp, url_prefix='/process')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5003, debug=True)
这其中,我们首先可以看到:
- 从router包中导入了三份蓝图对象,这得益于我们之前做的层层引入的工作(python包管理的相关操作)
app.register_blueprint()
函数,将蓝图对象进行注册
其中,app.register_blueprint()
函数的第二个参数url_prefix
是地址前缀的意思。
比如,我们在paper里面有一份路由叫/download_paper
, 那么外部进行访问的时候,必须通过/paper/download_paper
才能进行访问,也就是说,加上了一个固定的路由前缀。
注意:如果不完成注册,则无法使蓝图生效。
四、写在后面
以上,是一份较为清晰的蓝图介绍,希望能够对读者/新手有较大帮助。如果您有新想法,欢迎随时与我交流!