I have a function that I'm using to list routes for my Flask site and would like to be sure it is sorting them in the order in which they will be matched by Flask/Werkzeug.
Currently I have
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)
but this just seems to sort the routes in the order I've defined them in my code.
How do I sort Flask/Werkzeug routes in the order in which they will be matched?
Another approach: Specifying a host and a path and seeing what rule applies.
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
On each request Flask/Werkzeug reordered self.map.update()
rules if it need with route weights (see my another answer URL routing conflicts for static files in Flask dev server).
You can found that Map.update
method update _rules
(see https://github.com/mitsuhiko/werkzeug/blob/master/werkzeug/routing.py#L1313).
So you can do the same thing:
sorted(current_app.url_map._rules, key=lambda x: x.match_compare_key())
Or if all routes already loaded and any request done (called Map.build
or Map.match
) just use app.url_map._rules
- it will be sorted. In request app.url_map._rules
already sorted, because Map.match
was called before dispatcher (match rule with dispatcher).
You also can found that Map.update
called in Map.iter_rules
, so you can just use this method current_app.url_map.iter_rules()
(see https://github.com/mitsuhiko/werkzeug/blob/master/werkzeug/routing.py#L1161).