Blueprints
在 Flask 中,blueprint 是代表应用子集的逻辑结构。 blueprint 可以包括路由,视图函数,表单,模板和静态文件等元素。 如果在单独的 Python 包中编写 blueprint,那么你将拥有一个封装了应用特定功能的组件。
Blueprint 的内容最初处于休眠状态。 为了关联这些元素,blueprint 需要在应用中注册。 在注册过程中,需要将添加到 blueprint 中的所有元素传递给应用。 因此,你可以将 blueprint 视为应用功能的临时存储,以帮助组织代码。
错误处理 Blueprint
我创建的第一个 blueprint 用于封装对错误处理程序的支持。 该 blueprint 的结构如下:
app/
errors/ <-- blueprint package
__init__.py <-- blueprint creation
handlers.py <-- error handlers
templates/
errors/ <-- error templates
404.html
500.html
__init__.py <-- blueprint registration
实质上,我所做的是将 app/errors.py 模块移动到 app/errors/handlers.py 中,并将两个错误模板移动到 app/templates/errors 中,以便将它们与其他模板分开。 我还必须在两个错误处理程序中更改 render_template()
调用以使用新的 errors 模板子目录。 之后,我将 blueprint 创建添加到 app/errors/ init .py 模块,并在创建应用实例之后,将 blueprint 注册到 app/ init .py 。
我必须提一下,Flask blueprints 可以为自己的模板和静态文件配置单独的目录。 我已决定将模板移动到应用模板目录的子目录中,以便所有模板都位于一个层次结构中,但是如果你希望在 blueprint 中包含属于自己的模板,这也是支持的。 例如,如果向 Blueprint()
构造函数添加 template_folder='templates'
参数,则可以将错误 blueprint 的模板存储在 app/errors/templates 目录中。
创建 blueprint 与创建应用非常相似。 这是在 blueprint 的 ___init__.py
模块中完成的:
app/errors/__init__.py
:错误 blueprint。
from flask import Blueprint
bp = Blueprint('errors', __name__)
from app.errors import handlers
Blueprint
类获取 blueprint 的名称,基础模块的名称(通常在 Flask 应用实例中设置为 __name__
)以及一些可选参数(在这种情况下我不需要这些参数)。 Blueprint 对象创建后,我导入了 handlers.py 模块,以便其中的错误处理程序在 blueprint 中注册。 该导入位于底部以避免循环依赖。
在 handlers.py 模块中,我放弃使用 @app.errorhandler
装饰器将错误处理程序附加到应用程序,而是使用 blueprint 的 @bp.app_errorhandler
装饰器。 尽管两个装饰器最终都达到了相同的结果,但这样做的目的是试图使 blueprint 独立于应用,使其更具可移植性。我还需要修改两个错误模板的路径,因为它们被移动到了新 errors 子目录。
完成错误处理程序重构的最后一步是向应用注册 blueprint:
app/ init .py :向应用注册错误 blueprint。
app = Flask(__name__)
# ...
from app.errors import bp as errors_bp
app.register_blueprint(errors_bp)
# ...
from app import routes, models # <-- remove errors from this import!
为了注册 blueprint,将使用 Flask 应用实例的 register_blueprint()
方法。 在注册 blueprint 时,任何视图函数,模板,静态文件,错误处理程序等均连接到应用。 我将 blueprint 的导入放在 app.register_blueprint()
的上方,以避免循环依赖。
用户认证 Blueprint
将应用的认证功能重构为 blueprint 的过程与错误处理程序的过程非常相似。 以下是重构为 blueprint 的目录层次结构:
app/
auth/ <-- blueprint package
__init__.py <-- blueprint creation
email.py <-- authentication emails
forms.py <-- authentication forms
routes.py <-- authentication routes
templates/
auth/ <-- blueprint templates
login.html
register.html
reset_password_request.html
reset_password.html
__init__.py <-- blueprint registration
为了创建这个 blueprint,我必须将所有认证相关的功能移到为 blueprint 创建的新模块中。 这包括一些视图函数,Web 表单和支持功能,例如通过电子邮件发送密码重设 token 的功能。 我还将模板移动到一个子目录中,以将它们与应用的其余部分分开,就像我对错误页面所做的那样。
在 blueprint 中定义路由时,使用 @bp.route
装饰器来代替 @app.route
装饰器。 在 url_for()
中用于构建 URL 的语法也需要进行更改。 对于直接附加到应用的常规视图函数, url_for()
的第一个参数是视图函数名称。 但当在 blueprint 中定义路由时,该参数必须包含 blueprint 名称和视图函数名称,并以句点分隔。 因此,我不得不用诸如 url_for('auth.login')
的代码替换所有出现的 url_for('login')
代码,对于其余的视图函数也是如此。
注册 auth
blueprint 到应用时,我使用了些许不同的格式:
app/__init__.py
:注册用户认证 blueprint 到应用。
# ...
from app.auth import bp as auth_bp
app.register_blueprint(auth_bp, url_prefix='/auth')
# ...
在这种情况下, register_blueprint()
调用接收了一个额外的参数, url_prefix
。 这完全是可选的,Flask 提供了给 blueprint 的路由添加 URL 前缀的选项,因此 blueprint 中定义的任何路由都会在其完整 URL 中获取此前缀。 在许多情况下,这可以用来当成“命名空间”,它可以将 blueprint 中的所有路由与应用或其他 blueprint 中的其他路由分开。 对于用户认证,我认为让所有路由以 /auth 开头很不错,所以我添加了该前缀。 所以现在登录 URL 将会是 http://localhost:5000/auth/login 。 因为我使用 url_for()
来生成 URL,所有 URL 都会自动合并前缀。
主应用 Blueprint
第三个 blueprint 包含核心应用逻辑。 重构这个 blueprint 和前两个 blueprint 的过程一样。 我给这个 blueprint 命名为 main
,因此所有引用视图函数的 url_for()
调用都必须添加一个 main.
前缀。 鉴于这是应用的核心功能,我决定将模板留在原来的位置。 这不会有什么问题,因为我已将其他两个 blueprint 中的模板移动到子目录中了。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论