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

How do I sort Flask/Werkzeug routes in the order in which they will be matched?

我有一个函数,我用它来列出我的 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

根据每个请求 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.updateMap.iter_rules中被调用了,所以你可以直接使用这个方法current_app.url_map.iter_rules()(见https://github.com/mitsuhiko/werkzeug/blob/master/werkzeug/routing.py#L1161)。