Получить список всех маршрутов, определенных в приложении Flask


149

У меня есть сложное веб-приложение на основе Flask. Есть много отдельных файлов с функциями просмотра. Их URL-адреса определяются @app.route('/...')декоратором. Есть ли способ получить список всех маршрутов, которые были объявлены в моем приложении? Возможно, есть какой-нибудь метод, который я могу вызвать для appобъекта?

Ответы:


158

Все маршруты для приложения хранятся app.url_mapв экземпляре werkzeug.routing.Map. Вы можете перебирать Ruleэкземпляры, используя iter_rulesметод:

from flask import Flask, url_for

app = Flask(__name__)

def has_no_empty_params(rule):
    defaults = rule.defaults if rule.defaults is not None else ()
    arguments = rule.arguments if rule.arguments is not None else ()
    return len(defaults) >= len(arguments)


@app.route("/site-map")
def site_map():
    links = []
    for rule in app.url_map.iter_rules():
        # Filter out rules we can't navigate to in a browser
        # and rules that require parameters
        if "GET" in rule.methods and has_no_empty_params(rule):
            url = url_for(rule.endpoint, **(rule.defaults or {}))
            links.append((url, rule.endpoint))
    # links is now a list of url, endpoint tuples

См. Раздел Отображение ссылок на новые созданные веб-страницы для получения дополнительной информации.


Милая! За исключением того, что у меня возникла проблема с линией url = url_for(rule.endpoint). Я только что получил эту ошибку BuildError: ('DeleteEvent', {}, None). Вместо этого, чтобы получить URL, который я только что сделал url = rule.rule. Есть идеи, почему ваш метод не работает для меня?
J-bob

@ J-bob - скорее всего, связанный с маршрутом DeleteEventимеет обязательный параметр - вы можете либо использовать его в частном случае, либо отфильтровать любые правила, в которыхlen(rule.arguments) > len(rule.defaults)
Шон Виейра,

О, я думаю, я понял. url_forне может сгенерировать URL для этого метида без параметра, верно? Хорошо, но похоже, что мой метод все равно работает, он просто сохраняет эту часть, если URL-адрес является параметром. Благодарность!
J-bob

1
Это отличное начало. Есть ли предложения о том, как создать полностью самодокументированный веб-сервис на основе флакона, в котором перечислены все параметры (например,? Spam = "яйца")? Возможно, эту информацию можно извлечь из строки документации реализуемого метода.
Леонид

2
Вместо использования url_for(rule.endpoint)используйте rule.ruleэто намного лучше, потому что решайте случаи, когда у вас есть более одного маршрута для одного и того же метода.
Zini

89

Я только что встретил тот же вопрос. Это решение слишком сложно. Просто откройте новую оболочку под своим проектом:

    python
    >>> from app import app
    >>> app.url_map

Первое « приложение » - это мой скрипт проекта: app.py , второе - мое имя в сети.

(это решение для крошечной сети с небольшим маршрутом)


1
Вероятно, это не дает прямого ответа на вопрос. Но он, безусловно, заслуживает еще большего количества голосов.
UltraInstinct

Этот ответ отлично подходит для того, чтобы не требовать добавления кода в ваше приложение. Я использовал его, чтобы получить ответ за секунды, не перестраивая код.
joshdick 09

«Есть ли способ получить список всех маршрутов, которые были объявлены в моем приложении?» Я думаю, что это дает прямой ответ на вопрос и должен быть принятым ответом. Так просто. Спасибо.
andho 08

2
Я действительно не понимаю, как это проще или яснее, чем принятый ответ. Он предлагает тот же подход, но требует больше времени, чтобы добраться до сути, и не показывает, как выполнить итерацию по Mapэкземпляру или получить доступ к каким-либо свойствам, которые Ruleон содержит, без которых вы фактически не можете сделать что-либо полезное.
Марк Эмери

58

Я делаю вспомогательный метод на своем manage.py:

@manager.command
def list_routes():
    import urllib
    output = []
    for rule in app.url_map.iter_rules():

        options = {}
        for arg in rule.arguments:
            options[arg] = "[{0}]".format(arg)

        methods = ','.join(rule.methods)
        url = url_for(rule.endpoint, **options)
        line = urllib.unquote("{:50s} {:20s} {}".format(rule.endpoint, methods, url))
        output.append(line)

    for line in sorted(output):
        print line

Он решает недостающий аргумент, создавая фиктивный набор параметров. Результат выглядит так:

CampaignView:edit              HEAD,OPTIONS,GET     /account/[account_id]/campaigns/[campaign_id]/edit
CampaignView:get               HEAD,OPTIONS,GET     /account/[account_id]/campaign/[campaign_id]
CampaignView:new               HEAD,OPTIONS,GET     /account/[account_id]/new

Затем для его запуска:

python manage.py list_routes

Для получения дополнительной информации о проверке manage.py: http://flask-script.readthedocs.org/en/latest/


5
Вышеуказанное работает очень хорошо. Просто измените urllib.unquoteна urllib.parse.unquoteи print lineна, print(line)и он также работает в python 3.x.
ракель

1
Это не работает для нестроковых аргументов, я рекомендую вместо этого использовать ответ Джона Цзяна.
nico

42

Подобно ответу Джонатана, я решил сделать это вместо этого. Я не вижу смысла использовать url_for, поскольку он сломается, если ваши аргументы не строковые, например, float

@manager.command
def list_routes():
    import urllib

    output = []
    for rule in app.url_map.iter_rules():
        methods = ','.join(rule.methods)
        line = urllib.unquote("{:50s} {:20s} {}".format(rule.endpoint, methods, rule))
        output.append(line)

    for line in sorted(output):
        print(line)

37

Судя по всему, начиная с версии 0.11 во Flask есть встроенный CLI . Одна из встроенных команд выводит список маршрутов:

FLASK_APP='my_project.app' flask routes

Это просто великолепно!
pfabri

1
flask urlsдля меня (0.12.1). Видел это, flask --helpно я не вижу маршрутов или URL-адресов на странице CLI
mrgnw

маршруты, кажется, удалены во флаконе 1.1.2
Джерри Джи

5

Поскольку вы не указали, что он должен запускаться из командной строки, следующее можно легко вернуть в json для панели мониторинга или другого интерфейса, отличного от командной строки. В любом случае результат и результат не должны смешиваться с точки зрения дизайна. Это плохой дизайн программы, даже если это крошечная программа. Приведенный ниже результат можно затем использовать в веб-приложении, командной строке или в любом другом месте, которое принимает json.

Вы также не указали, что вам необходимо знать функцию python, связанную с каждым маршрутом, поэтому это более точно отвечает на ваш исходный вопрос.

Я использую ниже, чтобы сам добавить вывод на панель мониторинга. Если вам нужны доступные методы маршрута (GET, POST, PUT и т. Д.), Вам нужно будет объединить их с другими ответами выше.

Функция repr () правила выполняет преобразование необходимых аргументов в маршруте.

def list_routes():
    routes = []

    for rule in app.url_map.iter_rules():
        routes.append('%s' % rule)

    return routes

То же самое с пониманием списка:

def list_routes():
    return ['%s' % rule for rule in app.url_map.iter_rules()]

Пример вывода:

{
  "routes": [
    "/endpoint1", 
    "/nested/service/endpoint2", 
    "/favicon.ico", 
    "/static/<path:filename>"
  ]
}

3

Если вам необходимо получить доступ к самим функциям зрения, то вместо app.url_map, использование app.view_functions.

Пример сценария:

from flask import Flask

app = Flask(__name__)

@app.route('/foo/bar')
def route1():
    pass

@app.route('/qux/baz')
def route2():
    pass

for name, func in app.view_functions.items():
    print(name)
    print(func)
    print()

Результат выполнения сценария выше:

static
<bound method _PackageBoundObject.send_static_file of <Flask '__main__'>>

route1
<function route1 at 0x128f1b9d8>

route2
<function route2 at 0x128f1ba60>

(Обратите внимание на включение «статического» маршрута, который автоматически создается Flask.)


2

Вы можете просмотреть все маршруты через оболочку flask, выполнив следующие команды после экспорта или установки переменной среды FLASK_APP. flask shell app.url_map


1

внутри вашего фляжного приложения выполните:

flask shell
>>> app.url_map
Map([<Rule '/' (OPTIONS, HEAD, GET) -> helloworld>,
 <Rule '/static/<filename>' (OPTIONS, HEAD, GET) -> static>])
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.