1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
================================================================================
Request Routing
================================================================================
Bottle uses a powerful routing engine to find the right callback for each request. The :ref:`tutorial <tutorial-routing>` shows you the basics. This document covers advanced techniques and rule mechanics in detail.
Rule Syntax
--------------------------------------------------------------------------------
The :class:`Router` distinguishes between two basic types of routes: **static routes** (e.g. ``/contact``) and **dynamic routes** (e.g. ``/hello/<name>``). A route that contains one or more *wildcards* it is considered dynamic. All other routes are static.
.. versionchanged:: 0.10
The simplest form of a wildcard consists of a name enclosed in angle brackets (e.g. ``<name>``). The name should be unique for a given route and form a valid python identifier (alphanumeric, starting with a letter). This is because wildcards are used as keyword arguments for the request callback later.
Each wildcard matches one or more characters, but stops at the first slash (``/``). This equals a regular expression of ``[^/]+`` and ensures that only one path segment is matched and routes with more than one wildcard stay unambiguous.
The rule ``/<action>/<item>`` matches as follows:
============ =========================================
Path Result
============ =========================================
/save/123 ``{'action': 'save', 'item': '123'}``
/save/123/ `No Match`
/save/ `No Match`
//123 `No Match`
============ =========================================
Is it possible to escape characters like colon ``:`` with a backslash ``\``. This will prevent to trigger the old syntax in case you need to use ``:``.
For example: the rule ``/<action>/item:<id>`` triggers the old syntax, (see below) but ``/action/item\:<id>`` works as intended with the new syntax.
You can change the exact behaviour in many ways using filters. This is described in the next section.
Wildcard Filters
--------------------------------------------------------------------------------
.. versionadded:: 0.10
Filters are used to define more specific wildcards, and/or transform the matched part of the URL before it is passed to the callback. A filtered wildcard is declared as ``<name:filter>`` or ``<name:filter:config>``. The syntax for the optional config part depends on the filter used.
The following standard filters are implemented:
* **:int** matches (signed) digits and converts the value to integer.
* **:float** similar to :int but for decimal numbers.
* **:path** matches all characters including the slash character in a non-greedy way and may be used to match more than one path segment.
* **:re[:exp]** allows you to specify a custom regular expression in the config field. The matched value is not modified.
You can add your own filters to the router. All you need is a function that returns three elements: A regular expression string, a callable to convert the URL fragment to a python value, and a callable that does the opposite. The filter function is called with the configuration string as the only parameter and may parse it as needed::
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:
...
Legacy Syntax
--------------------------------------------------------------------------------
.. versionchanged:: 0.10
The new rule syntax was introduce in **Bottle 0.10** to simplify some common use cases, but the old syntax still works and you can find lot code examples still using it. The differences are best described by example:
=================== ====================
Old Syntax New Syntax
=================== ====================
``:name`` ``<name>``
``:name#regexp#`` ``<name:re:regexp>``
``:#regexp#`` ``<:re:regexp>``
``:##`` ``<:re>``
=================== ====================
Try to avoid the old syntax in future projects if you can. It is not currently deprecated, but will be eventually.
Explicit routing configuration
--------------------------------------------------------------------------------
Route decorator can also be directly called as method. This way provides flexibility in complex setups, allowing you to directly control, when and how routing configuration done.
Here is a basic example of explicit routing configuration for default bottle application::
def setup_routing():
bottle.route('/', 'GET', index)
bottle.route('/edit', ['GET', 'POST'], edit)
In fact, any :class:`Bottle` instance routing can be configured same way::
def setup_routing(app):
app.route('/new', ['GET', 'POST'], form_new)
app.route('/edit', ['GET', 'POST'], form_edit)
app = Bottle()
setup_routing(app)
|