Unterstützt Flask reguläre Ausdrücke im URL-Routing?

100

Ich verstehe, dass Flask die Konverter int, float und path hat, aber die Anwendung, die wir entwickeln, hat komplexere Muster in ihren URLs.

Gibt es eine Möglichkeit, reguläre Ausdrücke wie in Django zu verwenden?

Alistair
quelle

Antworten:

192

Obwohl Armin mich mit einer akzeptierten Antwort auf den Punkt gebracht hat, dachte ich, ich würde ein abgekürztes Beispiel dafür zeigen, wie ich einen Regex-Matcher in Flask implementiert habe, nur für den Fall, dass jemand ein funktionierendes Beispiel dafür haben möchte, wie dies getan werden kann.

from flask import Flask
from werkzeug.routing import BaseConverter

app = Flask(__name__)

class RegexConverter(BaseConverter):
    def __init__(self, url_map, *items):
        super(RegexConverter, self).__init__(url_map)
        self.regex = items[0]


app.url_map.converters['regex'] = RegexConverter

@app.route('/<regex("[abcABC0-9]{4,6}"):uid>-<slug>/')
def example(uid, slug):
    return "uid: %s, slug: %s" % (uid, slug)


if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=5000)

Diese URL sollte mit 200: http: // localhost: 5000 / abc0-foo / zurückgegeben werden

Diese URL sollte mit 404 zurückgegeben werden: http: // localhost: 5000 / abcd-foo /

Philip Southam
quelle
4
Aber bedeutet dies, dass die regulären Ausdrücke kompiliert oder im laufenden Betrieb ausgewertet werden?
Spiele Brainiac
1
Dies sieht so aus, als würde der reguläre Ausdruck direkt zur Laufzeit ausgewertet. Dies sollte für kleinere Apps (oder Apps, die Regex mehrmals wiederverwenden, würde ich denken) kein Problem sein, da die letzten Regex-Muster kompiliert im Speicher gespeichert werden.
Bbenne10
5
Wie funktioniert das? Das Muster ist auf eingestellt self.regex, aber wo findet die Übereinstimmung statt?
Justin
@Justin Das Matching findet in Werkzeugs Interna statt. Hier und irgendwo in der Definition einer Regel, die ich nicht gefunden habe.
AlexLordThorsen
49

Sie können benutzerdefinierte Konverter einbinden, die für beliebige Ausdrücke übereinstimmen: Benutzerdefinierter Konverter

from random import randrange
from werkzeug.routing import Rule, Map, BaseConverter, ValidationError

class BooleanConverter(BaseConverter):

    def __init__(self, url_map, randomify=False):
        super(BooleanConverter, self).__init__(url_map)
        self.randomify = randomify
        self.regex = '(?:yes|no|maybe)'

    def to_python(self, value):
        if value == 'maybe':
            if self.randomify:
                return not randrange(2)
            raise ValidationError()
        return value == 'yes'

    def to_url(self, value):
        return value and 'yes' or 'no'

url_map = Map([
    Rule('/vote/<bool:werkzeug_rocks>', endpoint='vote'),
    Rule('/vote/<bool(randomify=True):foo>', endpoint='foo')
], converters={'bool': BooleanConverter})
Armin Ronacher
quelle
Ich verstehe nicht, was to_pythontut
Corvid
17

Sie können auch einen Catch aller Routentypen schreiben und ein komplexes Routing innerhalb der Methode ausführen:

from flask import Flask
app = Flask(__name__)

@app.route('/', methods=['GET', 'POST'], defaults={'path': ''})
@app.route('/<path:path>', methods=['GET', 'POST'])
def catch_all(path):
    return 'You want path: %s' % path

if __name__ == '__main__':
    app.run()

Dies entspricht jeder Anfrage. Weitere Details finden Sie hier: Catch-All-URL .

Zorayr
quelle
Ich habe einen Fehler, würden Sie mir einige Hinweise geben? Datei "/app/catch_all.py", Zeile 234, in <module> @ app.route ('/ <Pfad: Pfad>', Methoden = ['GET']) Datei "/ usr / local / lib / python2. 7 / dist-packages / flask / app.py ", Zeile 1080, in der Dekorationsdatei" /usr/local/lib/python2.7/dist-packages/flask/app.py ", Zeile 64, in der Datei wrapper_func" / usr / local / lib / python2.7 / dist-packages / flask / app.py ", Zeile 1051, in add_url_rule 'vorhandene Endpunktfunktion:% s'% Endpunkt) AssertionError: Die Ansichtsfunktionszuordnung überschreibt eine vorhandene Endpunktfunktion: test
Funken