Поддерживает ли Flask регулярные выражения при маршрутизации URL-адресов?

#python #regex #flask

#python #регулярное выражение #flask

Вопрос:

Я понимаю, что у Flask есть преобразователи int, float и path, но приложение, которое мы разрабатываем, имеет более сложные шаблоны в своих URL-адресах.

Есть ли способ, которым мы можем использовать регулярные выражения, как в Django?

Ответ №1:

Несмотря на то, что Армин опередил меня с принятым ответом, я подумал, что покажу сокращенный пример того, как я реализовал сопоставитель регулярных выражений в Flask, на случай, если кому-то понадобится рабочий пример того, как это можно сделать.

 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)
  

этот URL должен возвращать значение 200:http://localhost:5000/abc0-foo /

этот URL должен будет вернуться с 404:http://localhost:5000/abcd-foo /

Комментарии:

1. Но означает ли это, что регулярные выражения компилируются или они вычисляются «на лету»?

2. Похоже, что регулярное выражение будет вычисляться непосредственно во время выполнения. Это не должно быть проблемой для небольших приложений (или приложений, которые повторно используют регулярное выражение несколько раз, я думаю), поскольку последние пару шаблонов регулярных выражений хранятся скомпилированными в памяти.

3. Как это работает? Шаблон имеет значение self.regex , но где происходит совпадение?

4. @Justin Совпадение происходит во внутренних компонентах Werkzeug Здесь и где-то в определении правила, которое я не нашел.

Ответ №2:

Вы можете подключить пользовательские конвертеры, которые соответствуют произвольным выражениям: Пользовательский конвертер

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

Комментарии:

1. Я не понимаю, что to_python делает

Ответ №3:

Вы также могли бы написать маршрут для всех типов и выполнять сложную маршрутизацию внутри метода:

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

Это будет соответствовать любому запросу. Смотрите более подробную информацию здесь: Универсальный URL.

Комментарии:

1. У меня ошибка, не могли бы вы дать мне несколько подсказок? Файл «/app/catch_all.py «, строка 234, в файле <module> @app.route(‘/<path:путь>’, методы=[‘GET’]) «/usr/local/lib/python2.7/dist-packages/flask/app.py «, строка 1080, в файле декоратора «/usr/local/lib/python2.7/dist-packages/flask/app.py «, строка 64, в файле wrapper_func «/usr/local/lib/python2.7/dist-packages/flask/app.py «, строка 1051, в add_url_rule ‘существующая функция конечной точки: %s’ % endpoint) Ошибка утверждения: отображение функции просмотра перезаписывает существующую функцию конечной точки: тест