URLプロセッサの使用—フラスコのドキュメント

提供:Dev Guides
< FlaskFlask/docs/1.0.x/patterns/urlprocessors
移動先:案内検索

URLプロセッサの使用

バージョン0.7の新機能。


Flask 0.7では、URLプロセッサの概念が導入されています。 アイデアは、URLに共通の部分があり、必ずしも明示的に提供したくないリソースがたくさんある可能性があるということです。 たとえば、言語コードが含まれているURLがたくさんある場合でも、すべての関数でそれを自分で処理する必要はありません。

URLプロセッサは、ブループリントと組み合わせると特に役立ちます。 ここでは、アプリケーション固有のURLプロセッサとブループリント固有の両方を扱います。

国際化されたアプリケーションのURL

次のようなアプリケーションについて考えてみます。

from flask import Flask, g

app = Flask(__name__)

@app.route('/<lang_code>/')
def index(lang_code):
    g.lang_code = lang_code
    ...

@app.route('/<lang_code>/about')
def about(lang_code):
    g.lang_code = lang_code
    ...

g オブジェクトの言語コード設定をすべての関数で自分で処理する必要があるため、これは非常に多くの繰り返しです。 もちろん、デコレータを使用してこれを単純化することもできますが、ある関数から別の関数にURLを生成する場合は、言語コードを明示的に指定する必要があり、煩わしい場合があります。

後者の場合、ここでurl_defaults()関数が登場します。 url_for()の呼び出しに値を自動的に挿入できます。 以下のコードは、言語コードがまだURL値のディクショナリにないかどうか、およびエンドポイントが'lang_code'という名前の値を必要としているかどうかを確認します。

@app.url_defaults
def add_language_code(endpoint, values):
    if 'lang_code' in values or not g.lang_code:
        return
    if app.url_map.is_endpoint_expecting(endpoint, 'lang_code'):
        values['lang_code'] = g.lang_code

URLマップのメソッドis_endpoint_expecting()を使用して、特定のエンドポイントに言語コードを提供することが理にかなっているかどうかを判断できます。

その逆の機能はurl_value_preprocessor()です。 リクエストが一致した直後に実行され、URL値に基づいてコードを実行できます。 アイデアは、値ディクショナリから情報を引き出して、別の場所に配置することです。

@app.url_value_preprocessor
def pull_lang_code(endpoint, values):
    g.lang_code = values.pop('lang_code', None)

そうすれば、すべての関数で lang_code を g に割り当てる必要がなくなります。 URLの前に言語コードを付ける独自のデコレータを作成することでさらに改善できますが、より美しい解決策はブループリントを使用することです。 'lang_code'が値ディクショナリからポップされ、ビュー関数に転送されなくなると、コードは次のようになります。

from flask import Flask, g

app = Flask(__name__)

@app.url_defaults
def add_language_code(endpoint, values):
    if 'lang_code' in values or not g.lang_code:
        return
    if app.url_map.is_endpoint_expecting(endpoint, 'lang_code'):
        values['lang_code'] = g.lang_code

@app.url_value_preprocessor
def pull_lang_code(endpoint, values):
    g.lang_code = values.pop('lang_code', None)

@app.route('/<lang_code>/')
def index():
    ...

@app.route('/<lang_code>/about')
def about():
    ...

国際化されたブループリントURL

ブループリントはすべてのURLに共通の文字列を自動的にプレフィックスとして付けることができるため、すべての関数に対して自動的にプレフィックスを付けるのは簡単です。 さらに、ブループリントはブループリントごとのURLプロセッサを持つことができ、URLが'lang_code'パラメータに本当に関心があるかどうかをチェックする必要がなくなるため、url_defaults()関数から多くのロジックを削除します。

from flask import Blueprint, g

bp = Blueprint('frontend', __name__, url_prefix='/<lang_code>')

@bp.url_defaults
def add_language_code(endpoint, values):
    values.setdefault('lang_code', g.lang_code)

@bp.url_value_preprocessor
def pull_lang_code(endpoint, values):
    g.lang_code = values.pop('lang_code')

@bp.route('/')
def index():
    ...

@bp.route('/about')
def about():
    ...