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

2024-04-29 10:34:49 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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

现在,我怎样才能打电话给url_for("foo")并且知道我将得到第一条路线?


Tags: path方法路径appurlforreturnfoo
3条回答

好的。对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 is /canonical/path/, alternative is /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"))

另外,对于那些使用由变量构造的catch all路由的用户:如果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>

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

烧瓶里的规矩是独一无二的。如果将绝对相同的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)

相关问题 更多 >