应用工厂 — Flask 文档

来自菜鸟教程
Flask/docs/2.0.x/patterns/appfactories
跳转至:导航、​搜索

应用工厂

如果您已经在为您的应用程序使用包和蓝图( 带有蓝图的模块化应用程序),有一些非常好的方法可以进一步改善体验。 一种常见的模式是在导入蓝图时创建应用程序对象。 但是,如果您将此对象的创建移动到一个函数中,则您可以稍后创建此应用程序的多个实例。

那么你为什么要这样做呢?

  1. 测试。 您可以使用具有不同设置的应用程序实例来测试每种情况。
  2. 多个实例。 想象一下,您想要运行同一应用程序的不同版本。 当然,您可以在 Web 服务器中设置多个具有不同配置的实例,但是如果您使用工厂,则可以在同一个应用程序进程中运行同一应用程序的多个实例,这很方便。

那么你将如何实际实施呢?

基础工厂

这个想法是在一个函数中设置应用程序。 像这样:

def create_app(config_filename):
    app = Flask(__name__)
    app.config.from_pyfile(config_filename)

    from yourapplication.model import db
    db.init_app(app)

    from yourapplication.views.admin import admin
    from yourapplication.views.frontend import frontend
    app.register_blueprint(admin)
    app.register_blueprint(frontend)

    return app

缺点是您不能在导入时在蓝图中使用应用程序对象。 但是,您可以在请求中使用它。 您如何使用配置访问应用程序? 使用 current_app

from flask import current_app, Blueprint, render_template
admin = Blueprint('admin', __name__, url_prefix='/admin')

@admin.route('/')
def index():
    return render_template(current_app.config['INDEX_TEMPLATE'])

在这里,我们在配置中查找模板的名称。


工厂和扩建

最好创建您的扩展程序和应用程序工厂,以便扩展程序对象最初不会绑定到应用程序。

Flask-SQLAlchemy 为例,您不应该按照以下方式执行某些操作:

def create_app(config_filename):
    app = Flask(__name__)
    app.config.from_pyfile(config_filename)

    db = SQLAlchemy(app)

但是,相反,在 model.py(或等效文件)中:

db = SQLAlchemy()

并在您的 application.py(或等效文件)中:

def create_app(config_filename):
    app = Flask(__name__)
    app.config.from_pyfile(config_filename)

    from yourapplication.model import db
    db.init_app(app)

使用这种设计模式,扩展对象上不会存储特定于应用程序的状态,因此一个扩展对象可以用于多个应用程序。 有关扩展设计的更多信息,请参阅 Flask 扩展开发


使用应用程序

要运行这样的应用程序,您可以使用 flask 命令:

Flask 会自动检测 myapp 中的工厂(create_appmake_app)。 您还可以像这样将参数传递给工厂:

然后使用字符串 'dev' 作为参数调用 myapp 中的 create_app 工厂。 有关更多详细信息,请参阅 命令行界面


工厂改进

上面的工厂函数不是很聪明,但是你可以改进它。 以下更改易于实施:

  1. 可以为单元测试传递配置值,这样您就不必在文件系统上创建配置文件。
  2. 在设置应用程序时从蓝图中调用一个函数,以便您有一个地方可以修改应用程序的属性(例如挂钩之前/之后的请求处理程序等)
  3. 如有必要,在创建应用程序时添加 WSGI 中间件。