如果我的方法有多个路由注释,如何使用url_for?

jig*_*ggy 37 python google-app-engine werkzeug flask

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

@app.route("/canonical/path/")
@app.route("/alternate/path/")
def foo():
    return "hi!"
Run Code Online (Sandbox Code Playgroud)

现在,我该如何打电话url_for("foo")并知道我将获得第一条路线?

Nem*_*den 65

好.它采取了一些潜心钻研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"))
Run Code Online (Sandbox Code Playgroud)

会产生

规范路径是/ 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"))
Run Code Online (Sandbox Code Playgroud)


Arm*_*her 51

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

有一个原因可能是您希望将多个URL连接到绝对相同的端点,并且这是与过去存在的规则的向后兼容性.从WZ0.8和Flask 0.8开始,您可以明确指定路由的别名:

@app.route('/')
@app.route('/index.html', alias=True)
def index():
    return ...
Run Code Online (Sandbox Code Playgroud)

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

这并不意味着函数不能绑定到多个url,但在这种情况下,您需要更改端点:

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

app.add_url_rule('/index.html', view_func=index, endpoint='alt_index')
Run Code Online (Sandbox Code Playgroud)

或者:

@app.route('/')
@app.route('/index.html', endpoint='alt_index')
def index():
    ...
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您可以使用其他名称第二次定义视图.但是,这通常是您要避免的,因为然后视图函数必须检查request.endpoint以查看所调用的内容.相反,更好地做这样的事情:

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

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

def _index(alt):
    ...
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,URL生成是url_for('index')url_for('alt_index').

您也可以在路由系统级别执行此操作:

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

在这种情况下,url生成是url_for('index', alt=True)url_for('index', alt=False).