Liste aller in der Flask-App definierten Routen abrufen

145

Ich habe eine komplexe Flask-basierte Web-App. Es gibt viele separate Dateien mit Ansichtsfunktionen. Ihre URLs werden mit dem @app.route('/...')Dekorateur definiert . Gibt es eine Möglichkeit, eine Liste aller Routen zu erhalten, die in meiner App deklariert wurden? Vielleicht gibt es eine Methode, die ich für das appObjekt aufrufen kann ?

J-Bob
quelle

Antworten:

152

Alle Routen für eine Anwendung werden gespeichert, auf app.url_mapdenen sich eine Instanz von befindet werkzeug.routing.Map. Sie können die RuleInstanzen mithilfe der folgenden iter_rulesMethode durchlaufen :

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

Weitere Informationen finden Sie unter Anzeigen von Links zu neuen Webseiten, die erstellt wurden .

Sean Vieira
quelle
Süss! Außer ich hatte ein Problem mit der Leitung url = url_for(rule.endpoint). Ich habe gerade diesen Fehler bekommen BuildError: ('DeleteEvent', {}, None). Stattdessen, um die URL zu bekommen, die ich gerade gemacht habe url = rule.rule. Irgendeine Idee, warum deine Methode bei mir nicht funktioniert?
J-Bob
@ J-Bob - höchstwahrscheinlich hat die zugeordnete Route DeleteEventeinen erforderlichen Parameter - Sie können entweder diesen Sonderfall oder alle Regeln herausfiltern, wolen(rule.arguments) > len(rule.defaults)
Sean Vieira
Oh, ich glaube ich verstehe. url_forkann die URL für diese Methode nicht ohne Parameter generieren, oder? OK, aber es sieht so aus, als ob meine Methode trotzdem funktioniert. Sie behält nur diesen Teil bei, wenn die URL ein Parameter ist. Vielen Dank!
J-Bob
1
Dies ist ein guter Anfang. Irgendwelche Vorschläge zum Erstellen eines vollständig selbstdokumentierenden flaschenbasierten Webdienstes, in dem alle Parameter (z. B.? Spam = "Eier") aufgelistet sind? Möglicherweise können diese Informationen aus einer Dokumentzeichenfolge einer Implementierungsmethode extrahiert werden.
Leonid
2
Statt Verwendung url_for(rule.endpoint)Verwendung , rule.ruledie viel besser beacause Fälle lösen , wo Sie mehr als eine Route für die gleiche Methode haben.
Zini
82

Ich habe gerade die gleiche Frage getroffen. Diese Lösung ist zu komplex. Öffnen Sie einfach eine neue Shell unter Ihrem Projekt:

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

Die erste ' App ' ist mein Projektskript: app.py , eine andere ist der Name meines Webs.

(Diese Lösung ist für winzige Netze mit einer kleinen Route)

Vi.Ci
quelle
1
Dies beantwortet die Frage wahrscheinlich nicht direkt. Aber es verdient sicher noch viel mehr Gegenstimmen.
UltraInstinct
Diese Antwort ist ideal, wenn Sie Ihrer Anwendung keinen Code hinzufügen müssen. Ich habe es verwendet, um die gewünschte Antwort in Sekunden zu erhalten, ohne meinen Code neu zu erstellen.
Joshdick
"Gibt es eine Möglichkeit, eine Liste aller Routen zu erhalten, die in meiner App deklariert wurden?" Ich denke, dies beantwortet die Frage direkt und sollte die akzeptierte Antwort sein. So einfach. Vielen Dank.
Andho
2
Ich sehe nicht wirklich, wie dies einfacher oder klarer ist als die akzeptierte Antwort. Es schlägt den gleichen Ansatz vor, dauert jedoch länger, bis der Punkt erreicht ist, und zeigt nicht, wie die MapInstanz durchlaufen oder auf die Eigenschaften der Ruledarin enthaltenen s zugegriffen werden kann, ohne die Sie eigentlich nichts Nützliches tun können.
Mark Amery
57

Ich mache eine Hilfsmethode für meine 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

Es löst das fehlende Argument, indem es einen Dummy-Satz von Optionen erstellt. Die Ausgabe sieht aus wie:

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

Dann, um es auszuführen:

python manage.py list_routes

Weitere Informationen zum Auschecken von manage.py finden Sie unter: http://flask-script.readthedocs.org/en/latest/

Jonathan
quelle
5
Das obige funktioniert sehr gut. Wechseln Sie einfach urllib.unquotezu urllib.parse.unquoteund print linezu print(line)und es funktioniert auch in Python 3.x.
Rakel
1
Dies funktioniert nicht für Argumente ohne Zeichenfolge. Ich empfehle stattdessen die Antwort von John Jiang.
Nico
42

Ähnlich wie bei Jonathans Antwort habe ich mich stattdessen dafür entschieden. Ich sehe keinen Sinn darin, url_for zu verwenden, da es kaputt geht, wenn Ihre Argumente keine Zeichenfolge sind, z. B. 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)
John Jiang
quelle
31

Anscheinend hat Flask seit Version 0.11 eine integrierte CLI . Einer der integrierten Befehle listet die Routen auf:

FLASK_APP='my_project.app' flask routes
theY4Kman
quelle
Das ist absolut genial!
Pfabri
1
flask urlsfür mich (0.12.1). flask --helpIch habe das gesehen, aber ich sehe keine Routen oder URLs auf der CLI-Seite
mrgnw
Routen scheinen in Flasche 1.1.2 entfernt zu sein
Jerry Ji
5

Da Sie nicht angegeben haben, dass die Befehlszeile ausgeführt werden muss, kann Folgendes in json für ein Dashboard oder eine andere Nicht-Befehlszeilenschnittstelle problemlos zurückgegeben werden. Das Ergebnis und die Ausgabe sollten sowieso nicht aus gestalterischer Sicht vermischt werden. Es ist ein schlechtes Programmdesign, auch wenn es ein winziges Programm ist. Das folgende Ergebnis kann dann in einer Webanwendung, einer Befehlszeile oder in anderen Elementen verwendet werden, die json aufnehmen.

Sie haben auch nicht angegeben, dass Sie die mit jeder Route verknüpfte Python-Funktion kennen müssen, damit Ihre ursprüngliche Frage genauer beantwortet wird.

Ich verwende unten, um die Ausgabe selbst einem Überwachungs-Dashboard hinzuzufügen. Wenn Sie die verfügbaren Routenmethoden (GET, POST, PUT usw.) verwenden möchten, müssen Sie sie mit anderen Antworten oben kombinieren.

Rule's repr () sorgt dafür, dass die erforderlichen Argumente in der Route konvertiert werden.

def list_routes():
    routes = []

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

    return routes

Das Gleiche mit einem Listenverständnis:

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

Beispielausgabe:

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

Wenn Sie die Ansicht Funktionen zugreifen selbst dann statt app.url_map, Verwendung app.view_functions.

Beispielskript:

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()

Ausgabe von der Ausführung des obigen Skripts:

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

route1
<function route1 at 0x128f1b9d8>

route2
<function route2 at 0x128f1ba60>

(Beachten Sie die Aufnahme der "statischen" Route, die von Flask automatisch erstellt wird.)

Mark Amery
quelle
2

Sie können alle Routen über die Flask-Shell anzeigen, indem Sie nach dem Exportieren oder Festlegen der Umgebungsvariablen FLASK_APP die folgenden Befehle ausführen. flask shell app.url_map

Xerrex
quelle
1

In Ihrer Kolben-App tun Sie Folgendes:

flask shell
>>> app.url_map
Map([<Rule '/' (OPTIONS, HEAD, GET) -> helloworld>,
 <Rule '/static/<filename>' (OPTIONS, HEAD, GET) -> static>])
Nabaz Maaruf
quelle