45

所以我有一个可以通过多条路线访问的方法:

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

现在,我怎么打电话url_for("foo")知道我会得到第一条路线?

4

3 回答 3

79

行。它需要一些钻研werkzeug.routingflask.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。所以,我想整个问题的正确解决方案是定义规范路径作为姓氏和名称的替代方案:

""" 
   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"))
于 2011-10-17T13:32:42.480 回答
51

Flask 中的规则是独一无二的。如果您为同一个函数定义绝对相同的 URL,默认情况下会发生冲突,因为您正在做一些我们阻止您做的事情,因为从我们的角度来看这是错误的。

您希望拥有多个指向绝对相同端点的 URL 有一个原因,那就是与过去存在的规则向后兼容。从 WZ0.8 和 Flask 0.8 开始,您可以为路由显式指定别名:

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

在这种情况下,如果用户请求/index.htmlFlask 会自动发出一个永久重定向到 just /

这并不意味着一个函数不能绑定到多个 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)or url_for('index', alt=False)

于 2011-10-24T13:07:50.647 回答
1

此外,对于那些使用由变量构建的全部路由的人:如果url_for传递包含变量的字典,Flask 将正确创建 url 路径。

例如...

应用程序.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)

测试.html:

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

当您单击“单击此处”链接时,您将被定向到“发布/创建”路线。

于 2015-03-24T21:57:34.710 回答