应用工厂¶
如果你已经在你的应用中使用包和蓝图 (使用蓝图的模块化应用),那么还有一些非常好的方法可以进一步改善体验。一个常见的模式是在导入蓝图时创建应用对象。但是,如果你将创建此对象的操作移到一个函数中,那么稍后你可以创建此应用的多个实例。
那么你为什么要这样做呢?
测试。你可以拥有具有不同设置的应用实例来测试每种情况。
多实例。想象一下,你想运行同一应用的多个版本。当然,你可以在你的网络服务器中设置具有不同配置的多个实例,但是如果你使用工厂,你可以在同一应用进程中运行同一应用的多个实例,这可能很方便。
那么你实际上会如何实现它呢?
基本工厂¶
想法是在一个函数中设置应用。像这样
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 --app hello run
Flask 将自动检测工厂,如果它在 hello
中被命名为 create_app
或 make_app
。你也可以像这样将参数传递给工厂
$ flask --app hello:create_app(local_auth=True) run
然后在 myapp
中的 create_app
工厂被调用,并带有关键字参数 local_auth=True
。有关更多详细信息,请参阅 命令行界面。
工厂改进¶
上面的工厂函数不是很智能,但是你可以改进它。以下更改很容易实现
使其可以为单元测试传入配置值,这样你就不必在文件系统上创建配置文件。
在应用设置时从蓝图调用一个函数,这样你就有了一个地方来修改应用的属性 (例如,挂钩在请求处理程序之前/之后等)。
在必要时,在创建应用时添加 WSGI 中间件。