11-flask框架-蓝图 Blueprint

一、蓝图应用的意义

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

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

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

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

  • 可以将一个Blueprint注册到任何一个未使用的URL下比如 “/”、“/sample”或者子域名,就是路由前缀

  • 在一个flask项目中,一个BluePrint模块可以注册多次

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

  • 在一个flask项目初始化时,就应该要注册需要使用的Blueprint

二、flask中使用蓝图的步骤

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

users=Blueprint('users',__name__)

2、在这个users蓝图目录下, 创建views.py文件,保存当前蓝图使用的视图函数

# 光写视图,不用写路由
def index():
    return "ok, users.views.index"

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

from flask import Blueprint
users = Blueprint("users",__name__)

from . import views
users.add_url_rule(rule="/index",view_func=views.index)
"""
users.add_url_rule(rule="/index",view_func=views.index)
等同于
views.py代码:
from . import users
@users.route("/index")   # ---> route方法就是调用了add_url_rule
def index():
    return "ok, users.views.index"
"""

4、在主应用manage.py文件中的app对象上注册这个users蓝图对象

from users import users
app.register_blueprint(users,url_prefix='/users')

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

三、蓝图运行机制

  • 蓝图Blueprint是保存了一组将来可以在flask应用对象上执行操作的路由关系.

  • 在视图上方调用 蓝图对象.route 装饰器注册路由时,这个操作本质就是将视图和url地址的映射关系添加到蓝图路由表的临时路由表中。

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

  • 在注册蓝图时,当执行app.register_blueprint() 时,应用对象app会将从蓝图对象的 defered_functions 列表中取出每一个路由项,并把app对象自己作为参数执行路由项对应的匿名函数,匿名函数执行以后就调用app.add_url_rule() 方法,这将蓝图下之前暂存的路由信息全部添加到了app.url_map路由表中了。

四、蓝图的url前缀

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

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

  • url_for在使用时,如果要生成一个蓝图里面的视图对应的路由地址,则需要声明当前蓝图名称+视图名称

五、注册蓝图中的静态文件的相关路由

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

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

users/__init__.py,代码:

from flask import Blueprint
users = Blueprint("users",__name__,static_folder="static_users")
from .views import *
users.add_url_rule(rule="/index",view_func=index)

manage.py,代码:

from flask import Flask
import config
# 应用实例对象
app = Flask(__name__)
# app.config.from_pyfile("config.py")
app.config.from_object(config)

# 导入蓝图并注册到app实例对象中
from users import users
app.register_blueprint(users,url_prefix="/users") # register_blueprint 内部循环调用了users里面注册的路由.

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

现在就可以使用/users/static_users/ 访问users/static_users/目录下的静态文件了.

 当然,也可以修改访问静态文件的路径 :可以在创建蓝图对象时使用 static_url_path 来改变静态目录的url地址。

from flask import Blueprint
users = Blueprint("users",__name__,static_folder="static_users",static_url_path="/st")

from .views import *
users.add_url_rule(rule="/index",view_func=index)

六、设置蓝图中模版的目录

蓝图对象中因为视图最终随着路由会被app实例对象所加载,所以原来蓝图中设置的模板目录会被默认的app指定模板目录所覆盖。所以,如果使用了蓝图下的模板目录就不要和app指定的模板目录同名,否则同名的模板文件就会被覆盖了。

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

from flask import Blueprint

users = Blueprint("users",__name__,template_folder="templates")

from . import views

users.add_url_rule("/index", view_func=views.index)

视图users.views,代码:

from flask import render_template
def index():
    data = {}
    data["title"] = "hello! users.index视图的数据"
    return render_template("index.html",**data)

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

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

 此时,访问效果:

 

 而此时如果在 项目的根目录下,也有一个templates 存在并也有一个index.html的同名模板文件时, 则系统会优先使用 根目录下的templates 中的模板文件。

templates/index.html,代码:

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

效果如下:

解决方案:如果使用了在蓝图下保存模板文件,则app应用实例对象初始化时的template_folder=None或者其他名字

 

原文地址:https://www.cnblogs.com/yj0405/p/14826782.html