【问题标题】:How do I sort Flask/Werkzeug routes in the order in which they will be matched?如何按匹配顺序对 Flask/Werkzeug 路由进行排序?
【发布时间】:2015-04-25 05:13:28
【问题描述】:

我有一个函数用于列出我的 Flask 站点的路由,并希望确保它按照 Flask/Werkzeug 匹配的顺序对它们进行排序。

目前我有

def routes(verbose, wide, nostatic):
    """List routes supported by the application"""

    for rule in sorted(app.url_map.iter_rules()):
        if nostatic and rule.endpoint == 'static':
            continue

        if verbose:
            fmt = "{:45s} {:30s} {:30s}" if wide else "{:35s} {:25s} {:25s}"
            line = fmt.format(rule, rule.endpoint, ','.join(rule.methods))
        else:
            fmt = "{:45s}" if wide else "{:35s}"
            line = fmt.format(rule)

        print(line)

但这似乎只是按照我在代码中定义的顺序对路由进行排序。

如何按匹配顺序对 Flask/Werkzeug 路由进行排序?


另一种方法:指定主机和路径并查看适用的规则。

    urls = app.url_map.bind(host)
    try:
        m = urls.match(match, "GET")
        z = '{}({})'.format(m[0], ','.join(["{}='{}'".format(arg, m[1][arg]) for arg in m[1]] +
                                           ["host='{}'".format(host)]))
        return z
    except NotFound:
        return

【问题讨论】:

  • 它们按此顺序显示,因为它们是这样存储的。请参阅github.com/mitsuhiko/werkzeug/blob/master/werkzeug/… 和其中的github.com/mitsuhiko/werkzeug/blob/master/werkzeug/… 了解内部工作原理:)
  • @JoeDoherty:sorted(app.url_map.iter_rules()) 也是按匹配顺序排列它们吗?
  • for rule in self.map._rules: 我认为它们没有排序。我能问一下你需要什么确切的订单吗?
  • @JoeDoherty:对于上面的函数。确保按照我想要的顺序检查它们。那么:如何按照匹配的顺序获取它们?
  • 去掉sorted() 应该是正确的。没有理由对其进行排序。

标签: flask url-routing werkzeug


【解决方案1】:

如果需要路由权重,Flask/Werkzeug 对每个请求重新排序 self.map.update() 规则(请参阅我的另一个答案 URL routing conflicts for static files in Flask dev server)。

可以发现Map.update方法更新_rules(见https://github.com/mitsuhiko/werkzeug/blob/master/werkzeug/routing.py#L1313)。

所以你可以做同样的事情:

sorted(current_app.url_map._rules, key=lambda x: x.match_compare_key())

或者,如果所有路由都已加载并且任何请求已完成(称为Map.buildMap.match),只需使用app.url_map._rules - 它将被排序。在请求中app.url_map._rules 已经排序,因为Map.match 在调度程序之前被调用(匹配规则与调度程序)。

你也可以发现Map.update调用了Map.iter_rules,所以你可以直接使用current_app.url_map.iter_rules()这个方法(见https://github.com/mitsuhiko/werkzeug/blob/master/werkzeug/routing.py#L1161)。

【讨论】:

  • 所以sorted(... x.match_compare_key())current_app.url_map.iter_rules() 将给出相同的结果(他们为我做的)并且该结果将被“排序”,对吗?
  • 令我困惑的是,如果这是真的,以static 开头的路径表现得非常奇怪。在我的开发机器和服务器上,(列出)代码的第一位最后列出了静态规则,这也是第二位代码的工作方式(将static 与非静态规则匹配)。这都是一致的。他在我的开发机器上的实际应用程序行为也是如此:我的规则而不是静态规则匹配静态路径。但是在服务器上,(尽管我的问题中的两段代码都将静态放在最后),静态规则会捕获任何静态路径!
  • 我回答中的所有示例都应该给出相同的结果。我不完全理解您的第二条评论,但您应该理解 static 路由与另一个相同 - 它具有从某个目录返回文件的规则和调度程序(端点)。在您的 prod 服务器上,静态路径可以根据配置被 nginx、apache 或其他 Web 服务器拦截。
  • 那么可能发生的是服务器是intercepting paths that begin with 'static' before Flask/Werkzeug 甚至有机会处理它们?
  • 也许,我不知道,但是 AWS 比开发人员更聪明并拦截此规则(不是静态,不是资产或其他东西)看起来很奇怪。您可以将应用程序的static_url_path 更改为不可预测,并检查它是否仍然正确(当您使用url_for 生成静态网址时它会正常工作)。
猜你喜欢
  • 2013-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-01
  • 2011-03-01
  • 2010-11-23
  • 1970-01-01
相关资源
最近更新 更多