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