¿Flask admite expresiones regulares en su enrutamiento de URL?

100

Entiendo que Flask tiene los convertidores int, float y path, pero la aplicación que estamos desarrollando tiene patrones más complejos en sus URL.

¿Hay alguna forma en que podamos usar expresiones regulares, como en Django?

Alistair
fuente

Respuestas:

192

Aunque Armin se me adelantó con una respuesta aceptada, pensé en mostrar un ejemplo abreviado de cómo implementé un comparador de expresiones regulares en Flask en caso de que alguien quiera un ejemplo práctico de cómo se podría hacer esto.

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)

esta URL debe regresar con 200: http: // localhost: 5000 / abc0-foo /

esta URL debería volver con 404: http: // localhost: 5000 / abcd-foo /

Philip Southam
fuente
4
Pero, ¿significa esto que las expresiones regulares se compilan o se evalúan sobre la marcha?
Juegos Brainiac
1
Parece que la expresión regular se evaluará directamente en tiempo de ejecución. Esto no debería ser problemático para aplicaciones más pequeñas (o aplicaciones que reutilizan expresiones regulares varias veces, creo) ya que el último par de patrones de expresiones regulares se almacenan compilados en la memoria.
bbenne10
5
¿Como funciona esto? El patrón está configurado self.regex, pero ¿dónde ocurre la coincidencia?
Justin
@Justin La coincidencia ocurre en las partes internas de Werkzeug Aquí y en algún lugar de la definición de una regla que no he encontrado.
AlexLordThorsen
49

Puede conectar convertidores personalizados que coincidan con expresiones arbitrarias: Convertidor personalizado

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
fuente
No entiendo lo que to_pythonhace
corvid
17

También puede escribir una captura de todo tipo de ruta y hacer enrutamiento complejo dentro del método:

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

Esto coincidirá con cualquier solicitud. Vea más detalles aquí: Catch-All URL .

Zorayr
fuente
Tengo un error, ¿podrías darme algunas pistas? Archivo "/app/catch_all.py", línea 234, en <module> @ app.route ('/ <ruta: ruta>', métodos = ['GET']) Archivo "/ usr / local / lib / python2. 7 / dist-packages / flask / app.py ", línea 1080, en el archivo decorador" /usr/local/lib/python2.7/dist-packages/flask/app.py ", línea 64, en el archivo wrapper_func" / usr / local / lib / python2.7 / dist-packages / flask / app.py ", línea 1051, en add_url_rule 'función de punto final existente:% s'% punto final) AssertionError: La asignación de función de vista está sobrescribiendo una función de punto final existente: prueba
chispa