请求路由

Bottle 使用强大的路由引擎为每个请求找到正确的处理函数。 教程 向你展示了基础知识。本文档详细介绍了高级技术和规则机制。

规则语法

Router 区分为两种基本类型的路由:静态路由(例如 /contact)和动态路由(例如 /hello/<name>)。包含一个或多个 通配符 的路由被认为是动态的。所有其他路由都是静态的。

0.10 版本中的变化。

通配符最简单的形式是由尖括号包围的名称(例如 <name>)。对于给定的路由,名称应该是唯一的,并形成有效的 Python 标识符(字母数字,以字母开头)。这是因为通配符稍后将用作请求处理函数的关键字参数。

每个通配符匹配一个或多个字符,但在第一个斜杠(/)处停止。这相当于正则表达式 [^/]+,并确保只匹配一个路径段,同时包含多个通配符的路由保持明确。

规则 /<action>/<item> 匹配如下

路径

结果

/save/123

{'action': 'save', 'item': '123'}

/save/123/

不匹配

/save/

不匹配

//123

不匹配

可以用反斜杠 \ 来转义冒号 : 等字符。这可以防止在需要使用 : 时触发旧语法。例如:规则 /<action>/item:<id> 会触发旧语法(见下文),而 /action/item\:<id> 则按新语法预期工作。

你可以使用过滤器以多种方式改变确切的行为。这将在下一节中描述。

通配符过滤器

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>

如果可以,请在未来的项目中尽量避免使用旧语法。它目前尚未弃用,但最终会。

显式路由配置

路由装饰器也可以作为方法直接调用。这种方式在复杂设置中提供了灵活性,允许你直接控制路由配置的时间和方式。

这是一个针对默认 Bottle 应用的显式路由配置的基本示例

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

实际上,任何 Bottle 实例的路由都可以用相同的方式配置

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

app = Bottle()
setup_routing(app)