URL映射

Bottle内置一个强大的route引擎,可以给每个浏览器请求找到正确的回调函数。 tutorial 中已经介绍了一些基础知识。接下来是一些进阶知识和route的规则。

route的语法

Router 类中明确区分两种类型的route: 静态route (例如 /contact )和 动态route (例如 /hello/<name> )。包含了 通配符 的route即是动态route,除此之外的都是静态的。

在 0.10 版更改.

包含通配符,最简单的形式就是将其放到一对<>里面(例如 <name> )。在同一个route里面,这个变量名需要是唯一的。因为稍后会将其当作参数传给回调函数,所以这个变量名的第一个字符应该是字母。

每一个通配符匹配一个或多个字符,直到遇到 / 。类似于 [^/]+ 这样一个正则表达式,确保在route包含多个通配符的时候不出现歧义。

/<action>/<item> 这个规则匹配的情况如下

路径

结果

保存/ 123

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

节省/ 123

不匹配

节省/

不匹配

/ / 123

不匹配

是否可以转义冒号之类的字符 : with a backslash \. This will prevent to trigger the old syntax in case you need to use :. For example: the rule `` /<action>/item:<id>``触发旧语法(见下文),但 /action/item\:<id> 按照新语法的预期工作。

你可通过过滤器来改变这一行为,稍后会介绍。

通配符过滤器

0.10 新版功能.

过滤器被用于定义更特殊的通配符,可在URL中"被匹配到的部分"被传递给回调函数之前,处理其内容。可通过 <name:filter><name:filer:config> 这样的语句来声明一个过滤器。"config"部分的语法由被使用的过滤器决定。

Bottle中已实现以下过滤器:

  • :int 匹配一个整形数,并将其转换为int

  • :float 同上,匹配一个浮点数

  • :path 匹配所有字符,包括'/'

  • :re[:exp] 允许在exp中写一个正则表达式

你可在route中添加自己写的过滤器。过滤器是一个有三个返回值的函数:一个正则表达式,一个callable的对象(转换URL片段为Python对象),另一个callable对象(转换Python对象为URL片段)。过滤器仅接受一个参数,就是设置字符串(译者注:例如re过滤器的exp部分)。

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>

请尽量在新项目中避免使用旧的语法,虽然它现在还没被废弃,但终究会的。

显式的route配置

route修饰器也可以直接当作函数来调用。在复杂的部署中,这种方法或许更灵活,直接由你来控制“何时”及“如何”配置route。

下面是一个简单的例子

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

实际上,bottle可以是任何 Bottle 类的实例

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

app = Bottle()
setup_routing(app)