Flask prend-il en charge les expressions régulières dans son routage d'URL?

100

Je comprends que Flask a les convertisseurs int, float et path, mais l'application que nous développons a des modèles plus complexes dans ses URL.

Existe-t-il un moyen d'utiliser des expressions régulières, comme dans Django?

Alistair
la source

Réponses:

192

Même si Armin m'a battu avec une réponse acceptée, j'ai pensé montrer un exemple abrégé de la façon dont j'ai implémenté un matcher regex dans Flask au cas où quelqu'un voudrait un exemple fonctionnel de la façon dont cela pourrait être fait.

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)

cette URL doit renvoyer avec 200: http: // localhost: 5000 / abc0-foo /

cette URL devrait renvoyer avec 404: http: // localhost: 5000 / abcd-foo /

Philip Southam
la source
4
Mais cela signifie-t-il que les expressions régulières sont compilées ou sont-elles évaluées à la volée?
Games Brainiac
1
Cela ressemble à l'expression régulière sera évaluée directement au moment de l'exécution. Cela ne devrait pas poser de problème pour les applications plus petites (ou les applications qui réutilisent plusieurs fois les regex, je pense) car les deux derniers modèles de regex sont stockés compilés en mémoire.
bbenne10
5
Comment cela marche-t-il? Le modèle est défini sur self.regex, mais où se produit la correspondance?
Justin
@Justin La correspondance se produit dans les internes de Werkzeug Ici et quelque part dans la définition d'une règle que je n'ai pas trouvée.
AlexLordThorsen
49

Vous pouvez accrocher des convertisseurs personnalisés qui correspondent à des expressions arbitraires: Convertisseur personnalisé

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
la source
Je ne comprends pas ce que to_pythonfait
corvid
17

Vous pouvez également écrire un type de route catch all et effectuer un routage complexe dans la méthode:

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

Cela correspondra à toute demande. Pour en savoir plus, cliquez ici: URL attrape-tout .

Zorayr
la source
J'ai une erreur, pourriez-vous me donner des indices? Fichier "/app/catch_all.py", ligne 234, dans <module> @ app.route ('/ <chemin: chemin>', methods = ['GET']) Fichier "/ usr / local / lib / python2. 7 / dist-packages / flask / app.py ", ligne 1080, dans le fichier décorateur" /usr/local/lib/python2.7/dist-packages/flask/app.py ", ligne 64, dans le fichier wrapper_func" / usr / local / lib / python2.7 / dist-packages / flask / app.py ", ligne 1051, dans add_url_rule 'fonction de point de terminaison existante:% s'% endpoint) AssertionError: le mappage de la fonction View écrase une fonction de point de terminaison existante: test
spark le