Flask使用蓝图的概念 来制作应用程序组件 和 支持应用程序内部 或 跨应用程序的通用模式 蓝图可以大大简化大型应用程序的工作方式,并为Falsk扩展提供了在应用程序上注册操作的中心手段。 Blueprint对象的工作方式于Falsk应用程序对象类似,但实际上它不是一个应用程序。 总之,蓝图可以使我们的程序更加模块化,不同功能的路由可以放在不同的模块下,最后集中到启动类中
蓝图使用起来就像应用中的子应用一样,可以有自己的模板,静态目录,有自己的视图函数和URL规则 蓝图之间互相不影响,但是它们又属于应用中,可以共享应用中的配置,对于大型应用来说,我们可以通过添加 蓝图来拓展应用功能,而不至于影响原来的程序,不过需要注意的是,目前Flask蓝图的注册时静态的,不支持可插拔 (比较好的习惯是将蓝图放在一个单独的文件包中,虽然多个蓝图可以共存同一个文件夹下,但是最好不要这样做。)
下面是我的项目文件目录,注册了蓝图admin和home
蓝图的注册
在运行文件app.py中加入 app.register_blueprint(admin, url_prefix="/admin") admin是创建的蓝图对象
这里我在admin下的admin_module.py中创建蓝图,
from flask import Blueprint, render_template
admin = Blueprint("admin", __name__, template_folder="templates", static_folder="static")
"""
这里将演示Flask中蓝图的使用,在项目下创建了一个admin包,在当前文件下来编写蓝图
我们创建了蓝图对象"admin_db",它使用起来和Flask应用的app对象类似,它有自己的路由"admin_db.route()"
初始化Blueprint对象的第一个参数"admin"指定了这个蓝图的名称,第二个参数指定了蓝图所在的模块名
这里再稍微说下python中的特殊属性 __name__ 当用在一个文件里时,代表的是模块(或包)的名字
我们可以指定蓝图自己的模板目录和静态目录,比如我们创建蓝图时传入:
admin_db = Blueprint("admin", __name__, template_folder="templates", static_folder="static")
"""
# 这里这个defaults对应/<a>这个值,如果后面有输入变量,则默认为小白
@admin.route("/<a>", defaults={"a": "小白"})
def index(a):
return render_template("admin/index.html", data=a)
@admin.route("/")
def test():
return render_template("admin/index.html")
同时我又在pro文件夹下又注册了蓝图home,对应的home_module.py代码如下
from flask import Blueprint, render_template
# template_folder="templates", static_folder="static", 这里没有指定的templates的话默认也是这两个值,
# 但是如果在这个蓝图前面也有蓝图是这样写的话,当前蓝图可以会到前面蓝图中的templates中查找同名html,
# 所以官方建议按照 home/templates/home/***.html的目录结构建立模板,这样的话蓝图查找模板内容就不会出错了
home_db = Blueprint("home", __name__, url_prefix="/home")
@home_db.route("/")
def index():
return render_template("index.html")
蓝图资源
这里需要注意的是,我在admin中把html模板放在了 templates/admin/index.html 这样的目录下,这样是为了区分蓝图home和admin的模板,官方的建议是按照 admin/templates/admin/***.html 这样的方式存放模板(官方文档)
如果admin的模板路径和home的模板路径一样都为 templates/***.html这样的格式的话,在我调用http://127.0.0.1:5000/admin/
显示的是蓝图admin下templates中的index.html没有错,但是如果后面我调用http://127.0.0.1:5000/home/所显示出来的index.html页面还是admin中的index.html页面,问题就展示出来了,如果有两个蓝图或多个蓝图,它们的模板目录都为 ***/templates/***.html这样的结构,如果在它们的templates下有着同名html文件,那么后面的蓝图加载的同名html文件会是第一个蓝图中的html
蓝图构建URL
使用url_for(),第一个参数我们称为端点,例如我们在该项目中创建的蓝图名 "admin",创建Blueprint对象时的第一个参数 所以我们通过端点名称来获取URL时,我们可以这样写: form flask import url_for url_for("admin.index") # return /admin/ url_for("admin.static",filename="style.css") # return /admin/static/style.css 这样才能获得"admin"蓝图下视图或资源的URL地址,如果"url_for()"函数的调用就在本蓝图下, 那么蓝图名就可以省略,但是必须留下"."表示当前蓝图: url_for(".index") url_for(".static",filename="style.css")
例如admin下的测试HTML index中的js由下列代码所示加载
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--这里给蓝图加载js,前加上admin-->
<script type="text/javascript" src="{{ url_for("admin.static",filename="js/jquery-1.8.3.min.js") }}"></script>
</head>
<body>
<h1>这是一个测试{{ data }},来自admin</h1>
</body>
</html>
当然也可以使用相对路径的方式加载: ../pro/admin/static/js/jquery-1.8.3.min.js
如果项目不大的话可以不使用的蓝图的方式,一开始接触的时候,看到别人的文件目录都是把templates文件夹放到和运行文件不同级的目录下,最开始我也按照那种方式创建文件目录,当时我并没有注册蓝图,所以在app.py中的视图函数一直找不到templates下的html文件,直到创建蓝图后才发现,app.py中视图函数没有找到html的话,会到蓝图下的templates中去找同名的html文件,
例如我的app.py中
from flask import Flask, render_template
from pro.admin.admin_module import admin
from pro.home.home_module import home_db
app = Flask(__name__, template_folder="template")
app.register_blueprint(admin, url_prefix="/admin") # url_prefix="/admin" 指定蓝图的URL前缀
app.register_blueprint(home_db) # 这里没有指定URL前缀是因为在创建蓝图时就设置好了
@app.route('/<name>')
def hello_world(name):
return render_template("app.html", data=name)
上面代码中,我建立Flask对象时,指定的template_folder="template" ,如下图所示,所以app.py中的视图函数会到同级目录中的template中去找对应的html, 如果没有指定template_folder,且没有在同级目录中创建templates文件夹,那么app.py的视图函数会到蓝图下的templates中去找相同名字的html
学习笔记仅供参考,