Отримайте список усіх маршрутів, визначених у програмі Flask


145

У мене є складний веб-додаток на основі колби. Існує безліч окремих файлів з функціями перегляду. Їх URL-адреси визначаються за допомогою @app.route('/...')декоратора. Чи є спосіб отримати список усіх маршрутів, оголошених у моєму додатку? Можливо, є якийсь метод, який я можу викликати на appоб’єкті?

Відповіді:


152

Всі маршрути для програми зберігаються, на 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 = "яйця")? Можливо, ця інформація може бути витягнута з docstring методу реалізації.
Леонід

2
Замість використання url_for(rule.endpoint)використовуйте rule.ruleце набагато краще, тому що вирішуйте випадки, коли у вас є один маршрут для одного методу.
Зіні

84

Я щойно зустріла те саме питання. Наведене вище рішення занадто складне. Просто відкрийте нову оболонку під своїм проектом:

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

Перший " додаток " - це мій сценарій проекту: app.py , інший - ім'я моєї мережі.

(це рішення для крихітного Інтернету з невеликим маршрутом)


1
Це, мабуть, не відповідає безпосередньо на питання. Але це, безумовно, заслуговує на набагато більше результатів.
UltraInstinct

Ця відповідь відмінно підходить для того, що вам не потрібно додавати код до своєї програми. Я використовував його, щоб отримати відповідь, яку я хотів за лічені секунди, не будуючи свій код.
Джошдик

"Чи є спосіб отримати список усіх маршрутів, оголошених у моєму додатку?" Я думаю, що це відповідає безпосередньо на питання і має бути прийнятою відповіддю. Так легко. Дякую.
andho

2
Я насправді не бачу, наскільки ця простіша чи зрозуміліша відповідь. Він пропонує той самий підхід, але потрібно довше, щоб дійти до суті, і не показує, як перебрати Mapекземпляр або отримати доступ до будь-якого з властивостей Rules, який він містить, без якого ви не можете зробити нічого корисного.
Марк Амері

57

Я роблю допоміжний метод на моїх 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

Докладніше про check.py замовлення: http://flask-script.readthedocs.org/en/latest/


5
Сказане працює дуже добре. Просто змініть urllib.unquoteна urllib.parse.unquoteі print lineна print(line)і вона працює в пітона 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)

32

Мабуть, з версії 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>"
  ]
}

2

Якщо вам потрібно отримати доступ до самих функцій перегляду, то замість цього 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_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.