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