Flask可以有可选的URL参数吗?

354

直接声明 Flask URL 的可选参数是否可能?

目前,我是按照以下方式进行的:

@user.route('/<userId>')
@user.route('/<userId>/<username>')
def show(userId, username=None):
    pass

我该如何直接表达username是可选的?

11个回答

488

另一种方法是写作

@user.route('/<user_id>', defaults={'username': None})
@user.route('/<user_id>/<username>')
def show(user_id, username):
    pass

但我想你希望编写一个单一的路由并将username标记为可选的?如果是这样,我认为这是不可能的。


在引用端点和url_for时使用此方法会出现问题吗? - user427165
2
据我所知没有。即使 Flask 的文档(http://flask.pocoo.org/docs/api/#url-route-registrations)中也包含类似的示例(您需要向下滚动一点才能看到它)。 - Audrius Kažukauskas
1
你可以尝试使用pip install flask_optional_routes。我为你所请求的功能创建了一个pip,因为我自己也需要它。代码位于:https://github.com/sudouser2010/flask_optional_routes。 - sudouser2010
如果您的主页上有多个选项卡,每个选项卡触发类似于/one/two/three/four之类的内容,并且您想在同一页上加载不同的内容而无需重新加载页面,那么您应该使用单个路由还是多个路由?已点赞! - PirateApp
能否将这两个路由分成两个函数? - Q. Qiao
显示剩余6条评论

241

这几乎和几个月前Audrius做的一样,但你可能会发现函数头中的默认值使其更易读 - 这是您使用Python的方式:

@app.route('/<user_id>')
@app.route('/<user_id>/<username>')
def show(user_id, username='Anonymous'):
    return user_id + ':' + username

4
如果username不是常量,这个方法也同样适用。defaults=会将默认值冻结在字典中。 - kasperhj
4
我倾向于这个选项。我们应该尽可能保持代码的整洁。 - Light.G
3
请注意这里有一个重要的警告:如果您有多个位置参数,而不是所有参数都是可选的,Flask 将无法正确构建 URL。您可能会得到类似于 /page?arg=foo 的东西,而实际上应该是 /foo/page。@Audrius Kažukauskas 的答案在这种情况下有效,但这并不是最佳解决方案。 - rgargente
1
这也可以防止Flask在省略可选的URI路径参数时重定向为308。例如,如果您在上面的默认值中使用defaults=方法,并且在URI的一部分指定与username可选参数相同的Anonymous字符串,那么您将得到一个308重定向到/<user_id> - geudrik
1
这也可以防止 Flask 在省略可选的 URI 路径参数时进行 308 重定向。例如,如果您在上面的默认值中使用 defaults= 方法,并且在 URI 的一部分中指定与 username 可选参数相同的 Anonymous 字符串,您将得到一个 308 重定向,将您重定向到 /<user_id> - undefined

90

如果你和我一样使用Flask-Restful,也可以这样做:

api.add_resource(UserAPI, '/<userId>', '/<userId>/<username>', endpoint = 'user')

然后在您的资源类中:

class UserAPI(Resource):

  def get(self, userId, username=None):
    pass

35

16

6
你应该在这里添加外部链接的信息,因为如果该链接无效,你的答案将受到损害。 - tomab
2
该链接已失效。幸运的是,我们有archive.org(https://web.archive.org/web/20190414194437/https://flask.pocoo.org/snippets/57/)。 - m3nda

15
@user.route('/<user_id>', defaults={'username': default_value})
@user.route('/<user_id>/<username>')
def show(user_id, username):
   #
   pass

8

与skornos几乎相同,但使用变量声明可以更明确地回答。它可以与Flask-RESTful扩展一起使用:

from flask import Flask
from flask_restful import Resource, Api

app = Flask(__name__)
api = Api(app)

class UserAPI(Resource):
    def show(userId, username=None):
    pass

api.add_resource(UserAPI, '/<userId>', '/<userId>/<username>', endpoint='user')

if __name__ == '__main__':
    app.run()
< p > add_resource 方法允许通过多个URL。每个URL将被路由到您的Resource


5

我知道这篇文章很老,但我曾经开发过一个名为"flask_optional_routes"的包来实现此功能。代码位于:https://github.com/sudouser2010/flask_optional_routes

from flask import Flask

from flask_optional_routes import OptionalRoutes


app = Flask(__name__)
optional = OptionalRoutes(app)

@optional.routes('/<user_id>/<user_name>?/')
def foobar(user_id, user_name=None):
    return 'it worked!'

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=5000)

0

你可以像示例中展示的那样编写,但是这样会导致构建错误。

为了解决这个问题:

  1. 在你的根.py文件中打印app.url_map()
  2. 你会看到类似于以下内容:

<Rule '/<userId>/<username>' (HEAD, POST, OPTIONS, GET) -> user.show_0>

<Rule '/<userId>' (HEAD, POST, OPTIONS, GET) -> .show_1>

  1. 然后在模板中你可以使用{{ url_for('.show_0', args) }}{{ url_for('.show_1', args) }}

-8

自 Flask 0.10 版本开始,您无法将多个路由添加到一个端点。但是您可以添加虚假的端点。

@user.route('/<userId>')
def show(userId):
   return show_with_username(userId)

@user.route('/<userId>/<username>')
def show_with_username(userId,username=None):
   pass

7
什么?我这里使用的是 Flask 0.10.1 版本,我可以很好地将多个路由添加到一个端点。 - jaapz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接