2011-10-16 3 views

答えて

58

werkzeug.routingflask.helpers.url_forコードを掘り下げて調べましたが、わかりました。あなただけ(あなたは名前あなたのルート、つまり)

正規のパスを生成します

@app.route("/canonical/path/", endpoint="foo-canonical") 
@app.route("/alternate/path/") 
def foo(): 
    return "hi!" 

@app.route("/wheee") 
def bar(): 
    return "canonical path is %s, alternative is %s" % (url_for("foo-canonical"), url_for("foo")) 

ルートの endpointを変更/正規の/パス/で、代替は/代替/パスです/

このアプローチの欠点があります。 Flaskは、暗黙的に定義されたエンドポイントへの最後に定義されたルートを常にバインドします(コードではfoo)。エンドポイントを再定義するとどうなるでしょうか? url_for('old_endpoint')はすべてwerkzeug.routing.BuildErrorです。フラスコ内の

""" 
    since url_for('foo') will be used for canonical path 
    we don't have other options rather then defining an endpoint for 
    alternative path, so we can use it with url_for 
""" 
@app.route('/alternative/path', endpoint='foo-alternative') 
""" 
    we dont wanna mess with the endpoint here - 
    we want url_for('foo') to be pointing to the canonical path 
""" 
@app.route('/canonical/path') 
def foo(): 
    pass 

@app.route('/wheee') 
def bar(): 
    return "canonical path is %s, alternative is %s" % (url_for("foo"), url_for("foo-alternative")) 
+1

徹底的で素敵な答えです。私に確認の機会を与え、私はそれを受け入れるとマークします。あなたはpocooの人々にこれを提出して、正式に文書化されるべきです。 – jiggy

+0

フラスコ0.8にアップグレードするまではこれで問題がありました(0.7.2で失敗しました)。それはまた、私にとって最後のものではなく、最初の注釈を取り上げているようです。いずれにしても、エンドポイントのパラメータがキーです。 – jiggy

48

ルールがユニークである:だから、私は、全体の問題に適したソリューションが最後と名に代替を正規のパスを定義していると思います。同じ関数に絶対同じURLを定義した場合、デフォルトでは衝突してしまいます。なぜなら、私たちの視点から間違っているからやってやることをやめてしまうからです。

絶対に同じエンドポイントに複数のURLを設定し、過去に存在していたルールとの下位互換性を持たせる理由の1つがあります。ユーザーは/index.htmlフラスコを自動的に恒久的にちょうど/へのリダイレクトを発行します要求した場合この場合

@app.route('/') 
@app.route('/index.html', alias=True) 
def index(): 
    return ... 

:WZ0.8とフラスコ0.8ので、明示的にルートのエイリアスを指定することができます。

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

app.add_url_rule('/index.html', view_func=index, endpoint='alt_index') 

または代わりに::

@app.route('/') 
@app.route('/index.html', endpoint='alt_index') 
def index(): 
    ... 

機能がが複数のURLにバインドすることができませんでしたが、この場合には、あなたがエンドポイントを変更する必要があるだろうという意味ではありません

この場合、ビューを別の名前で2回定義することができます。しかし、これは一般的に避けたいものです。なぜなら、ビュー関数は呼び出されたものを見るためにrequest.endpointをチェックする必要があるからです。これらの例のURL生成の両方で

@app.route('/') 
def index(): 
    return _index(alt=False) 

@app.route('/index.html') 
def alt_index(): 
    return _index(alt=True) 

def _index(alt): 
    ... 

url_for('index')url_for('alt_index')です:代わりに、より良いことは、このような何かを行います。

また、ルーティングシステムレベルでこれを行うことができます。

@app.route('/', defaults={'alt': False}) 
@app.route('/index.html', defaults={'alt': True}) 
def index(alt): 
    ... 

この場合、URL生成はurl_for('index', alt=True)またはurl_for('index', alt=False)です。

+0

これをドキュメントに入れておいた方がいいですか?最後の例はまさに私に必要なものでした。 – aplavin

0

さらに、変数を使用してキャッチされたすべての経路を使用する場合:Flaskは、変数を含む辞書がurl_forに渡された場合、urlパスを正しく作成します。例えば

は...

app.py:

app.route('/<path:pattern1>') 
app.route('/<path:pattern1>/<path:pattern2>') 
def catch_all(pattern1, pattern2=None): 
    return render_template('template.html', p1=pattern1, p2=pattern2) 

app.route('/test') 
def test_routing: 
    args = {'pattern1': 'Posts', 'pattern2': 'create'} 
    return render_template('test.html', args=args) 

test.htmlという:あなたは 'ここをクリック' リンクをクリックすると

<a href="{{url_for('catch_all', **args)}}">click here</a> 

、あなたが指示されます「投稿/作成」ルートに移動します。

関連する問題