flask 蓝图 Blueprint

模块化

随着flask程序越来越复杂,我们需要对程序进行模块化的处理,之前学习过django的子应用管理,flask程序进行可以进行类似的模块化处理保存代码。

简单来说,Blueprint 是一个存储视图方法/模型代码的容器(目录),这些操作在这个Blueprint 被注册到flask的APP实例对象应用之后就可以被调用,Flask 可以通过Blueprint来组织URL以及处理客户端请求的视图。

Flask使用Blueprint让应用实现模块化,在Flask中Blueprint具有如下属性:

  • 一个项目可以具有多个Blueprint

  • 可以将一个Blueprint注册到任何一个未使用的URL下比如 “/”、“/users”或者子域名,也就是说每一个蓝图都可以像django那样有属于自己的路由前缀

  • 在一个flask项目中,同一个BluePrint模块可以注册多次,也就是说一个蓝图可以对应多个不同的url地址。

  • Blueprint目录可以保存单独属于自己的模板目录保存自己的模板文件、静态文件或者其它的通用操作方法,它并不是必须要实现应用的视图和函数的

  • 在一个flask项目初始化时,就应该要注册需要使用的Blueprint,否则项目不识别Blueprint蓝图

注意:flask中的Blueprint并不是一个完整的项目应用,它不能独立运行,而必须要把蓝图blueprint注册到某一个flask项目中才能使用。

在flask中,要使用蓝图Blueprint可以分为四个步骤:

1.手动创建一个蓝图的包目录,例如users,并在__init__.py文件中创建蓝图实例对象users_blueprint

users/__init.py,代码:

from flask import Blueprint

# 等同于 app = Flask(__name__),只是这里并非一个独立的flask项目,
# 所以需要在第一个参数中,指定蓝图名称,其他参数与之前实例化app应用对象是一样的。
users_blueprint = Blueprint("users", __name__)

2.在这个users蓝图目录下创建蓝图的子文件, 其中我们可以创建views.py文件,保存当前蓝图使用的视图函数

users/views.py,代码:

# 光写视图,不用写路由
def login():
    return "用户登录视图"

def register():
    return "用户注册视图"

3.在users/__init__.py中引入views.py中所有的视图函数并绑定路由,users/__init__.py,代码:

from flask import Blueprint
from . import views

# 等同于 app = Flask(__name__),只是这里并非一个独立的flask项目,
# 所以需要在第一个参数中,指定蓝图名称,其他参数与之前实例化app应用对象是一样的。
users_blueprint = Blueprint("users", __name__)

# 把蓝图下的视图与蓝图下的路由进行绑定
users_blueprint.add_url_rule(rule="/login", view_func=views.login)
users_blueprint.add_url_rule(rule="/register", view_func=views.register)

4.在主应用下程序入口manage.py文件中把这个users_blueprint蓝图对象注册app实例对象中,运行起来。

manage.py,代码:

from flask import Flask

app = Flask(__name__)

# 注册蓝图
from users import users_blueprint
app.register_blueprint(blueprint=users_blueprint, url_prefix="/users")

if __name__ == '__main__':
    app.run(debug=True)

当这个应用启动后,通过/users/login或者/users/register可以访问到蓝图中定义的视图函数

蓝图运行机制

  • 蓝图Blueprint实际上的作用就是,充当当前蓝图目录下的所有视图和url路由地址的绑定关系的临时容器

  • 在视图函数被蓝图对象的add_url_rule方法注册时,这个操作本质就是将视图和url地址的映射关系添加到蓝图的子路由列表deferred_functions中。

  • 蓝图对象根本没有路由机制的,当我们在蓝图中的视图函数上调用route装饰器(或者add_url_role函数)注册路由时,它只是在蓝图对象的内部的 deferred_functions(子路由列表)中添加了一个路由项(路由项实际上就是一个绑定了视图和url地址的lambda匿名函数)

  • 当执行app.register_blueprint()注册蓝图时,app应用实例对象会将从蓝图对象的 deferred_functions列表中循环取出每一个之前注册的路由项,并把app应用实例对象自己作为参数执行路由项对应的lambda匿名函数,lambda匿名函数执行以后就会调用app.add_url_rule() 方法,这就将蓝图下子路由列表之前暂存的路由全部添加到了app应用实例对象的url_map总路由表中了,所以用户就可以在flask中访问到了蓝图中的视图。当然,能访问蓝图下的视图,自然也就可以通过视图调用其他的功能,例如:蓝图下的其他功能函数或其他的模型对象了。

蓝图的url拼接

当我们在app应用实例对象上注册一个蓝图时,可以指定一个url_prefix关键字参数(这个参数默认是/)

在app应用实例对象的最终的路由表 url_map中,在蓝图上注册的路由URL自动被加上了这个路由前缀,这个可以保证在多个蓝图中使用相同的子路由而不会最终引起冲突,只要在注册蓝图时将不同的蓝图挂接到不同的自路径即可。

注意:有了蓝图以后,在flask使用url_for在使用时,如果要生成一个蓝图里面的视图对应的路由地址,则需要声明当前蓝图名称+视图名称

# url_for('蓝图名称.视图函数名')
url_for('users.login') # /users + /login   /users就是蓝图中的路由前缀  /login就是子路由

注册蓝图下的静态文件[很少使用]

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

下面的代码将蓝图所在目录下的static_users目录设置为静态目录

users/__init__.py,代码:

from flask import Blueprint
from . import views

# 等同于 app = Flask(__name__),只是这里并非一个独立的flask项目,
# 所以需要在第一个参数中,指定蓝图名称,其他参数与之前实例化app应用对象是一样的。
users_blueprint = Blueprint("users", __name__, static_folder="static")

# 把蓝图下的视图与蓝图下的路由进行绑定
users_blueprint.add_url_rule(rule="/login", view_func=views.login)
users_blueprint.add_url_rule(rule="/register", view_func=views.register)

print(users_blueprint.deferred_functions)

现在就可以使用http://127.0.0.1:5000/users/static/6.png 访问users/static/目录下的静态文件了。

设置蓝图下的html模版[很少使用]

创建蓝图下的模板目录templates,users/__init__.py,代码:

from flask import Blueprint
from . import views

# 等同于 app = Flask(__name__),只是这里并非一个独立的flask项目,
# 所以需要在第一个参数中,指定蓝图名称,其他参数与之前实例化app应用对象是一样的。
users_blueprint = Blueprint("users", __name__, static_folder="static", template_folder="templates")

# 把蓝图下的视图与蓝图下的路由进行绑定
users_blueprint.add_url_rule(rule="/login", view_func=views.login)
users_blueprint.add_url_rule(rule="/register", view_func=views.register)

print(users_blueprint.deferred_functions)

视图users/views.py,代码:

from flask import url_for, render_template
# 光写视图,不用写路由
def login():
    title = "用户登录视图"
    return render_template("login.html", **locals())

def register():
    return f"用户注册视图,登录视图的url地址:{url_for('users.login')}"

模板代码,users/templates/login.html,代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
  <h1>{{title}}</h1>
  <p>templates/login.html</p>
</body>
</html>

注意:

如果使用了flask1.x版本,则不能出现项目根目录下和蓝图目录下2个templates目录的情况,否则项目根目录下的templates模板会覆盖蓝图目录下的同名模板,flask会优先加载项目根目录下的模板。flask2.x版本已经解决上面的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值