Ottieni l'elenco di tutti i percorsi definiti nell'app Flask


145

Ho una complessa app web basata su Flask. Esistono molti file separati con funzioni di visualizzazione. I loro URL sono definiti con il @app.route('/...')decoratore. C'è un modo per ottenere un elenco di tutti i percorsi che sono stati dichiarati in tutta la mia app? Forse esiste un metodo che posso chiamare appsull'oggetto?

Risposte:


152

Tutti i percorsi per un'applicazione sono memorizzati su app.url_mapcui è presente un'istanza di werkzeug.routing.Map. È possibile scorrere le Ruleistanze utilizzando il iter_rulesmetodo:

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

Vedere Visualizzare collegamenti a nuove pagine Web create per ulteriori informazioni.


Dolce! Tranne che ho avuto un problema con la linea url = url_for(rule.endpoint). Ho appena ricevuto questo errore BuildError: ('DeleteEvent', {}, None). Invece, per ottenere l'URL ho appena fatto url = rule.rule. Hai idea del perché il tuo metodo non funziona per me?
J-bob,

@ J-bob - molto probabilmente il percorso associato DeleteEventha un parametro richiesto - puoi sia quello speciale che uno o filtrare eventuali regole in cuilen(rule.arguments) > len(rule.defaults)
Sean Vieira

Oh penso di averlo capito. url_fornon puoi generare l'URL per quel methid senza un parametro, giusto? OK, ma sembra che il mio metodo funzioni comunque, mantiene solo quella parte se l'URL come parametro. Grazie!
J-bob,

1
Questo è un ottimo inizio. Qualche suggerimento su come creare un servizio web basato su matraccio completamente auto-documentante, in cui sono elencati tutti i parametri (come? Spam = "uova")? Forse queste informazioni possono essere estratte da una documentazione di un metodo di implementazione.
Leonid,

2
Invece di usare l' url_for(rule.endpoint)uso rule.ruleè molto meglio perché risolvere i casi in cui hai più di un percorso per lo stesso metodo.
Zini,

84

Ho appena incontrato la stessa domanda. Quella soluzione sopra è troppo complessa. Basta aprire una nuova shell sotto il tuo progetto:

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

La prima ' app ' è lo script del mio progetto: app.py , un altro è il nome del mio web.

(questa soluzione è per la piccola rete con un piccolo itinerario)


1
Questo probabilmente non risponde direttamente alla domanda. Ma sicuramente merita molti più voti.
UltraInstinct

Questa risposta è ottima per non aver bisogno di aggiungere alcun codice alla tua applicazione. L'ho usato per ottenere la risposta che volevo in pochi secondi senza ricostruire il mio codice.
joshdick,

"C'è un modo per ottenere un elenco di tutti i percorsi che sono stati dichiarati in tutta la mia app?" Penso che questo risponda direttamente alla domanda e dovrebbe essere la risposta accettata. Così facile. Grazie.
andho

2
Non vedo davvero come questo sia più semplice o più chiaro della risposta accettata. Sta suggerendo lo stesso approccio, ma richiede più tempo per arrivare al punto e non mostra come iterare sull'istanza Mapo accedere a nessuna delle proprietà della Rules che contiene, senza la quale non si può effettivamente fare nulla di utile.
Mark Amery,

57

Faccio un metodo di supporto sul mio 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

Risolve l'argomento mancante costruendo una serie fittizia di opzioni. L'output è simile a:

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

Quindi eseguirlo:

python manage.py list_routes

Per ulteriori informazioni sul checkout manage.py: http://flask-script.readthedocs.org/en/latest/


5
Quanto sopra funziona molto bene. Basta passare urllib.unquotea urllib.parse.unquotee print linea print(line)e funziona anche in Python 3.x.
tergipavimento

1
Questo non funziona per argomenti senza stringhe, consiglio invece di usare la risposta di John Jiang.
nico,

42

Simile alla risposta di Jonathan, invece, ho deciso di farlo. Non vedo il punto di usare url_for poiché si romperà se i tuoi argomenti non sono stringhe, ad esempio 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

Apparentemente, dalla versione 0.11, Flask ha una CLI integrata . Uno dei comandi integrati elenca i percorsi:

FLASK_APP='my_project.app' flask routes

Questo è assolutamente geniale!
pfabri

1
flask urlsper me (0.12.1). L' flask --helpho visto ma non vedo i percorsi o gli URL nella pagina della CLI
mrgnw

le rotte sembrano essere rimosse nel pallone 1.1.2
Jerry Ji l'

5

Poiché non è stato specificato che deve essere eseguito dalla riga di comando, è possibile che in Json venga facilmente restituito un dashboard o un'altra interfaccia non da riga di comando. In ogni caso, il risultato e l'output non dovrebbero essere mescolati dal punto di vista del design. È una cattiva progettazione del programma, anche se è un programma minuscolo. Il risultato che segue potrebbe quindi essere utilizzato in un'applicazione Web, nella riga di comando o in qualsiasi altra cosa che ingerisca json.

Inoltre, non hai specificato che dovevi conoscere la funzione Python associata a ciascuna rotta, quindi questo risponde più precisamente alla tua domanda originale.

Uso di seguito per aggiungere personalmente l'output a una dashboard di monitoraggio. Se desideri i metodi di percorso disponibili (GET, POST, PUT, ecc.), Dovrai combinarlo con altre risposte sopra.

Il repr () di Rule si occupa di convertire gli argomenti richiesti nella rotta.

def list_routes():
    routes = []

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

    return routes

La stessa cosa usando una comprensione della lista:

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

Uscita campione:

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

2

Se è necessario accedere alle funzioni di visualizzazione stesse app.url_map, utilizzare inveceapp.view_functions .

Script di esempio:

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

Output dall'esecuzione dello script sopra:

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

route1
<function route1 at 0x128f1b9d8>

route2
<function route2 at 0x128f1ba60>

(Notare l'inclusione della route "statica", che viene creata automaticamente da Flask.)


2

È possibile visualizzare tutte le rotte tramite shell boccetta eseguendo i seguenti comandi dopo aver esportato o impostato la variabile di ambiente FLASK_APP. flask shell app.url_map


1

nell'app della beuta fai:

flask shell
>>> app.url_map
Map([<Rule '/' (OPTIONS, HEAD, GET) -> helloworld>,
 <Rule '/static/<filename>' (OPTIONS, HEAD, GET) -> static>])
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.