アプリケーションファクトリ

すでにあなたのアプリケーションでパッケージやモジュールを使っている場合( packages )、より良くする方法がいくつかあります。よくあるパターンとしてはモジュールがインポートされたときにアプリケーションオブジェクトを生成する方法です。しかし、このオブジェクト生成のコードをたとえば関数内に動かした場合、このインスタンスを複数作成できます。

ではなぜこうしたいんでしょうか?

  1. テストのため。あらゆるケースをテストするために異なる設定のアプリケーションインスタンを作ることが出来ます。
  2. 複数のインスタンスを作成するため。同じアプリケーションを複数バージョン実行したいとしましょう。 もちろんWebサーバ内で複数のインスタンスを異なる設定で走らせることも出来ます。しかしもしファクトリを使えば、 複数のアプリケーションのインスタンスを同じぷる添え素手実行することが出来ます。お手軽ですよね。

では実際にどうやって実装するのでしょうか。

基本的なファクトリ

アイデアとしては、アプリケーションを関数内でセットアップする、という方法です。こんな具合です。:

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

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

    return app

下の方でアプリケーションオブジェクトをモジュールのインポート時には使うことはできません。 しかしリクエストの中では使うことが出来ます。どのように設定内でアプリケーションにアクセスするんでしょうか。 current_app を使いましょう。:

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

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

これで設定内のテンプレートの名前を参照できます。

アプリケーションを使う

このようなアプリケーションを使うためには、まずアプリケーションを作成しなければなりません。 そのようなアプリケーションを実行する run.py の例を以下に示します。:

from yourapplication import create_app
app = create_app('/path/to/config.cfg')
app.run()

ファクトリの改良

上に挙げたファクトリ関数はあまり賢くはありませんが、これを改良することはできます。 以下に挙げるような改良が簡単で実行可能なものでしょう。:

  1. 設定値をユニットテストに渡すことが出来るようにして、ファイルシステム内に設定ファイルを置かなくて済むようにする
  2. アプリケーションが立ち上がるときにモジュールから関数を呼び、アプリケーションの属性を変更できる余地を作る。(例えばリクエストハンドラの前後にフックを作るなど)
  3. 必要があればアプリケーションが生成されているときにWSGIミドルウェアを追加する。