ビューを怠惰にロードする
フラスコは通常、デコレータで使用されます。 デコレータは単純で、その特定のURLに対して呼び出される関数のすぐ隣にURLがあります。 ただし、このアプローチには欠点があります。つまり、デコレータを使用するすべてのコードを事前にインポートする必要があります。そうしないと、Flaskが実際に関数を見つけることができません。
アプリケーションをすばやくインポートする必要がある場合、これは問題になる可能性があります。 GoogleのAppEngineやその他のシステムなどのシステムでそれを行う必要があるかもしれません。 したがって、アプリケーションがこのアプローチを超えていることに突然気付いた場合は、一元化されたURLマッピングにフォールバックできます。
中央URLマップを持つことを可能にするシステムはadd_url_rule()
機能です。 デコレータを使用する代わりに、すべてのURLでアプリケーションを設定するファイルがあります。
一元化されたURLマップへの変換
現在のアプリケーションが次のようになっていると想像してください。
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
pass
@app.route('/user/<username>')
def user(username):
pass
次に、一元化されたアプローチでは、ビュー(views.py
)を含むが、デコレータを含まない1つのファイルがあります。
def index():
pass
def user(username):
pass
次に、関数をURLにマップするアプリケーションをセットアップするファイル:
from flask import Flask
from yourapplication import views
app = Flask(__name__)
app.add_url_rule('/', view_func=views.index)
app.add_url_rule('/user/<username>', view_func=views.user)
読み込みが遅い
これまでのところ、ビューとルーティングを分割するだけですが、モジュールはまだ前もってロードされています。 秘訣は、必要に応じて実際にビュー関数をロードすることです。 これは、関数と同じように動作するが、最初の使用時に実際の関数を内部的にインポートするヘルパークラスを使用して実行できます。
from werkzeug.utils import import_string, cached_property
class LazyView(object):
def __init__(self, import_name):
self.__module__, self.__name__ = import_name.rsplit('.', 1)
self.import_name = import_name
@cached_property
def view(self):
return import_string(self.import_name)
def __call__(self, *args, **kwargs):
return self.view(*args, **kwargs)
ここで重要なのは、 __ module __ と __ name __ が正しく設定されていることです。 これは、ルールの名前を自分で指定しない場合にURLルールに名前を付ける方法を理解するためにFlaskによって内部的に使用されます。
次に、次のようにビューを組み合わせるための中心的な場所を定義できます。
from flask import Flask
from yourapplication.helpers import LazyView
app = Flask(__name__)
app.add_url_rule('/',
view_func=LazyView('yourapplication.views.index'))
app.add_url_rule('/user/<username>',
view_func=LazyView('yourapplication.views.user'))
文字列の前にプロジェクト名とドットを付け、 view_func をラップすることで、add_url_rule()
を呼び出す関数を作成することで、これを書き込むために必要なキーストロークの量に関してこれをさらに最適化できます。必要に応じて LazyView で。
def url(import_name, url_rules=[], **options):
view = LazyView('yourapplication.' + import_name)
for url_rule in url_rules:
app.add_url_rule(url_rule, view_func=view, **options)
# add a single route to the index view
url('views.index', ['/'])
# add two routes to a single function endpoint
url_rules = ['/user/','/user/<username>']
url('views.user', url_rules)
覚えておくべきことの1つは、最初のリクエストで正しく機能するために、リクエストハンドラの前後が事前にインポートされたファイルに含まれている必要があるということです。 同じことが、残りのあらゆる種類のデコレータにも当てはまります。