Flask supporta le espressioni regolari nel suo instradamento URL?


100

Capisco che Flask abbia i convertitori int, float e path, ma l'applicazione che stiamo sviluppando ha modelli più complessi nei suoi URL.

C'è un modo in cui possiamo usare espressioni regolari, come in Django?

Risposte:


192

Anche se Armin mi ha battuto sul tempo con una risposta accettata, ho pensato di mostrare un esempio abbreviato di come ho implementato un abbinamento regex in Flask nel caso qualcuno volesse un esempio funzionante di come questo potrebbe essere fatto.

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)

questo URL dovrebbe restituire 200: http: // localhost: 5000 / abc0-foo /

questo URL dovrebbe restituire 404: http: // localhost: 5000 / abcd-foo /


4
Ma questo significa che le espressioni regolari vengono compilate o vengono valutate al volo?
Giochi Brainiac

1
Sembra che la regex verrà valutata direttamente in fase di esecuzione. Questo non dovrebbe essere problematico per le app più piccole (o le app che riutilizzano più volte le espressioni regolari, penso) poiché gli ultimi due modelli di espressioni regolari sono archiviati compilati in memoria.
bbenne10

5
Come funziona? Lo schema è impostato self.regex, ma dove avviene la corrispondenza?
Justin

@Justin L'abbinamento avviene negli interni di Werkzeug Qui e da qualche parte nella definizione di una regola che non ho trovato.
AlexLordThorsen

49

Puoi collegare convertitori personalizzati che corrispondono a espressioni arbitrarie: Convertitore personalizzato

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

Non capisco cosa to_pythonfa
corvid

17

Puoi anche scrivere un percorso di cattura di tutti i tipi e fare un percorso complesso all'interno del metodo:

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

Ciò corrisponderà a qualsiasi richiesta. Ulteriori dettagli qui: URL catch-all .


Ho un errore, mi daresti qualche indizio? File "/app/catch_all.py", riga 234, in <module> @ app.route ('/ <path: path>', methods = ['GET']) File "/ usr / local / lib / python2. 7 / dist-packages / flask / app.py ", riga 1080, nel file decorator" /usr/local/lib/python2.7/dist-packages/flask/app.py ", riga 64, nel file wrapper_func" / usr / local / lib / python2.7 / dist-packages / flask / app.py ", riga 1051, in add_url_rule 'existing endpoint function:% s'% endpoint) AssertionError: View function mapping is overwriting an existing endpoint function: test
scintilla il
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.