【发布时间】:2011-12-08 14:00:42
【问题描述】:
所以我有一个可以通过多条路线访问的方法:
@app.route("/canonical/path/")
@app.route("/alternate/path/")
def foo():
return "hi!"
现在,我如何拨打url_for("foo") 并知道我会得到第一条路线?
【问题讨论】:
标签: python google-app-engine flask werkzeug
所以我有一个可以通过多条路线访问的方法:
@app.route("/canonical/path/")
@app.route("/alternate/path/")
def foo():
return "hi!"
现在,我如何拨打url_for("foo") 并知道我会得到第一条路线?
【问题讨论】:
标签: python google-app-engine flask werkzeug
好的。对werkzeug.routing 和flask.helpers.url_for 代码进行了一些研究,但我已经弄清楚了。您只需更改路线的endpoint(换句话说,您命名您的路线)
@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"))
会产生
规范路径是/canonical/path/,替代路径是/alternate/path/
这种方法有一个缺点。 Flask 总是将最后定义的路由绑定到隐式定义的端点(代码中的foo)。猜猜如果重新定义端点会发生什么?你所有的url_for('old_endpoint') 都会抛出werkzeug.routing.BuildError。所以,我想整个问题的正确解决方案是定义规范路径最后一个和 name 替代:
"""
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"))
【讨论】:
Flask 中的规则是独一无二的。如果你为同一个函数定义了绝对相同的 URL,默认情况下会发生冲突,因为你正在做一些我们阻止你做的事情,因为从我们的角度来看这是错误的。
您希望拥有多个指向绝对相同端点的 URL 的原因之一是与过去存在的规则向后兼容。从 WZ0.8 和 Flask 0.8 开始,您可以为路由显式指定别名:
@app.route('/')
@app.route('/index.html', alias=True)
def index():
return ...
在这种情况下,如果用户请求 /index.html,Flask 将自动发出永久重定向到 /。
这并不意味着一个函数不能绑定到多个 url,但在这种情况下,您需要更改端点:
@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():
...
在这种情况下,您可以使用不同的名称再次定义视图。但是,这是您通常要避免的事情,因为视图函数必须检查 request.endpoint 以查看调用的内容。相反,最好做这样的事情:
@app.route('/')
def index():
return _index(alt=False)
@app.route('/index.html')
def alt_index():
return _index(alt=True)
def _index(alt):
...
在这两种情况下,URL 生成都是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)。
【讨论】:
此外,对于那些使用由变量构建的全部路由的用户:如果向url_for 传递包含变量的字典,Flask 将正确创建 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>
当您点击“点击此处”链接时,您将被引导至“发布/创建”路线。
【讨论】: