返回介绍

Blueprints

发布于 2025-01-02 21:53:56 字数 4832 浏览 0 评论 0 收藏

在 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 中的模板移动到子目录中了。

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。