Spec-Zone.ru › Bottle 0.11

Маршрутизация запросов

Bottle использует мощный движок маршрутизации для поиска подходящего обработчика для каждого запроса. Учебник показывает основы. Этот документ подробно описывает расширенные методы и механизмы правил.

Синтаксис правил

Ключевое слово Router различает два основных типа маршрутов: статические маршруты (например, /contact) и динамические маршруты (например, /hello/<name>). Маршрут, содержащий один или несколько подстановочных символов, считается динамическим. Все остальные маршруты являются статическими.

Изменено в версии 0.10.

Простейшая форма подстановочного символа состоит из имени в угловых скобках (например, <name>). Имя должно быть уникальным для данного маршрута и представлять собой допустимый идентификатор Python (буквенно-цифровой, начинающийся с буквы). Это связано с тем, что подстановочные символы используются в качестве ключевых аргументов для обратного вызова запроса позже.

Каждый подстановочный символ соответствует одному или нескольким символам, но останавливается на первой косой черте (/). Это эквивалентно регулярному выражению [^/]+ и гарантирует, что совпадает только один сегмент пути, и маршруты с более чем одним подстановочным символом остаются однозначными.

Правило /<action>/<item> сопоставляется следующим образом:

Путь Результат
/save/123 {'action': 'save', 'item': '123'}
/save/123/ No Match
/save/ No Match
//123 No Match

Вы можете изменить точное поведение многими способами, используя фильтры. Это описано в следующем разделе.

Фильтры подстановочных символов

Добавлена в версии 0.10.

Фильтры используются для определения более конкретных подстановочных символов и/или преобразования сопоставленной части URL-адреса перед передачей ее в обратный вызов. Отфильтрованный подстановочный символ объявляется как <name:filter> или <name:filter:config>. Синтаксис необязательной части конфигурации зависит от используемого фильтра.

Реализованы следующие стандартные фильтры:

  • :int соответствует (знаковым) цифрам и преобразует значение в целое число.
  • :float аналогичен :int, но для десятичных чисел.
  • :path сопоставляет все символы, включая косую черту, не жадным образом и может использоваться для сопоставления более одного сегмента пути.
  • :re[:exp] позволяет указать пользовательское регулярное выражение в поле конфигурации. Сопоставленное значение не изменяется.

Вы можете добавить свои собственные фильтры в маршрутизатор. Все, что вам нужно, — это функция, возвращающая три элемента: строку регулярного выражения, вызываемый объект для преобразования фрагмента URL-адреса в значение Python и вызываемый объект для выполнения обратного преобразования. Функция фильтра вызывается со строкой конфигурации в качестве единственного параметра и может анализировать ее по мере необходимости:

app = Bottle()

def list_filter(config):
    ''' Matches a comma separated list of numbers. '''
    delimiter = config or ','
    regexp = r'\d+(%s\d)*' % re.escape(delimiter)

    def to_python(match):
        return map(int, match.split(delimiter))

    def to_url(numbers):
        return delimiter.join(map(str, numbers))

    return regexp, to_python, to_url

app.router.add_filter('list', list_filter)

@app.route('/follow/<ids:list>')
def follow_users(ids):
    for id in ids:
        ...

Синтаксис предыдущих версий

Изменено в версии 0.10.

Новый синтаксис правил был введен в Bottle 0.10 для упрощения некоторых распространенных случаев использования, но старый синтаксис по-прежнему работает, и вы можете найти много примеров кода, которые все еще используют его. Различия лучше всего описать на примере:

Старый синтаксис Новый синтаксис
:name <name>
:name#regexp# <name:re:regexp>
:#regexp# <:re:regexp>
:## <:re>

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

Порядок маршрутизации

Благодаря подстановочным символам и регулярным выражениям можно определить перекрывающиеся маршруты. Если несколько маршрутов соответствуют одному и тому же URL-адресу, ситуация усложняется. Чтобы полностью понять, что происходит в этом случае, необходимо знать, в каком порядке маршрутизатор проверяет маршруты.

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

Статические маршруты проверяются в первую очередь. Это в основном для повышения производительности и может быть отключено, но в настоящее время является значением по умолчанию. Если ни один статический маршрут не соответствует запросу, проверяются динамические маршруты в том порядке, в котором они были определены. Первый совпавший маршрут завершает поиск. Если ни одно правило не совпало, возвращается ошибка «404 Страница не найдена».

На втором шаге проверяется метод запроса. Если не найдено точное совпадение, и метод запроса — HEAD, маршрутизатор проверяет маршрут GET. В противном случае он проверяет маршрут ANY. Если и это не сработает, возвращается ошибка «405 Метод запрещен».

Вот пример, где это может вас затруднить:

@route('/<action>/<name>', method='GET')
@route('/save/<name>', method='POST')

Второй маршрут никогда не будет обработан. Даже запросы POST не попадают ко второму маршруту, потому что метод запроса проверяется на отдельном шаге. Маршрутизатор останавливается на первом маршруте, который соответствует пути запроса, затем проверяет наличие допустимого метода запроса, не находит его и поднимает ошибку 405.

Звучит сложно, и это так. Такова цена производительности. Лучше всего избегать неоднозначных маршрутов и выбирать уникальные префиксы для каждого маршрута. Однако эта реализация может быть изменена в будущем. Мы над этим работаем.

Явное конфигурирование маршрутизации

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

Вот базовый пример явного конфигурирования маршрутизации для приложения Bottle по умолчанию:

def setup_routing():
    bottle.route('/', method='GET', index)
    bottle.route('/edit', method=['GET', 'POST'], edit)

Фактически, любой Bottle экземпляр маршрутизации можно настроить аналогичным образом:

def setup_routing(app):
    app.route('/new', method=['GET', 'POST'], form_new)
    app.route('/edit', method=['GET', 'POST'], form_edit)

app = Bottle()
setup_routing(app)

© 2009–2017 Marcel Hellkamp
Licensed under the MIT License.
https://bottlepy.org/docs/0.11/routing.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API