Как отсортировать маршруты Flask/Werkzeug в том порядке, в котором они будут сопоставлены?

У меня есть функция, которую я использую для составления списка маршрутов для своего сайта 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

1 ответ

Решение

По каждому запросу Flask/Werkzeug переупорядочивается self.map.update() правила, если это необходимо, с весами маршрутов (см. мой другой ответ URL конфликты маршрутизации для статических файлов на сервере Flask dev).

Вы можете найти это Map.update обновление метода _rules (см. https://github.com/mitsuhiko/werkzeug/blob/master/werkzeug/routing.py).

Так что вы можете сделать то же самое:

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

Или если все маршруты уже загружены и какой-либо запрос выполнен (называется Map.build или же Map.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).

Другие вопросы по тегам