1. Andriy Kornatskyy
  2. wheezy.routing


wheezy.routing / doc / userguide.rst

User Guide

Pattern and Handler

You create a mapping between: pattern (a remainder of the request URL, script name, http schema, host name or whatever else) and handler (callable, string, etc.):

urls = [
     ('posts/2003', posts_for_2003),
     ('posts/{year}', posts_by_year),
     ('posts/(?P<year>\d+)/(?P<month>\d+)', posts_by_month)

It is completely up to you how to interpret pattern (you can add own patterns interpretation) and/or handler. If you have a look at :ref:`helloworld` example you notice the following:

or more precisely:


This operation takes WSGI environment varible PATH_INFO and pass to router for matching against available mapping. handler in this case is a simple callable that represents WSGI call handler.

Extend Mapping

Since mapping is nothing more than python list, you can make any manipulation you like, e.g. add other mappings, construct them dynamically, etc. Here is snippet from :ref:`server time` example:

home mapping has been extended by simple adding another list.

Mapping Inclusion

Your application may be constructed with several modules, each of them can have own url mapping. You can easily include them as a handler (the system checks if the handler is another mapping it creates nested PathRouter). Here is an example from :ref:`server time`:

server_urls included into server/ subpath. So effective path for server_time handler is server/time.

Note that route selected for 'server/' pattern is intermediate (it is not finishing since there is included another after it). 'time' pattern is finishing since it is the last in the match chain.

Named Groups

Named groups is something that you can get out from url mapping:

urls = [
    ('posts/{year}', posts_by_year),
    ('posts/(?P<year>\d+)/(?P<month>\d+)', posts_by_month)

kwargs is assigned with dict that represends a key-value pair from match:

>>> handler, kwargs = r.match('posts/2011/09')
>>> kwargs
{'month': '09', 'year': '2011'}

Extra Parameters

While named groups get some information from matched path, you can also merge with some extra values during initialization of mapping (this is third parameter in tupple):

urls = [
    ('posts', latest_posts, {'blog_id': 100})

Note, that any non-empty values from path match override extra parameters passed during initialization.

url helper

There is :py:func:`wheezy.routing.router.url` function that let you make your url mapping more readable:

from wheezy.routing import url

urls = [
    url('posts', latest_posts, kwargs={'blog_id': 100})

All it does just convers arguments to a tupple of four.

Named Mapping

Each path mapping you create is automatically named after the handler name. The convention as to the name is: translate handler name from camel case to underscope name and remove anything ended by handler, controller, etc. So LatestPostsHandler is named as latest_posts.

You can specify other name during mapping, it is convenient to use :py:func:`~wheezy.routing.router.url`) function for this:

urls = [
    url('posts', latest_posts, name='posts')

When you know name for url mapping you can reconstruct it path.

Adding Routes

You have an instance of :py:class:`~wheezy.routing.router.PathRouter`. Call it method :py:meth:`~wheezy.routing.router.PathRouter.add_routes` to add any pattern mapping you have. Here is how we do it in :ref:`helloworld` example:

... or :ref:`server time`:

Route Builders

Every pattern mapping you add to router is translated to appropriate route match strategy. The available routing match strategies are definded in :py:mod:`~wheezy.routing.config` module by route_builders list and include:

  1. plain
  2. regex
  3. curly

You can easily extend this list with your own route strategies.

Plain Route

The plain route is selected in case the path satisfy the following regular expression (at least one word, '/' or '-' character):

The matching paths include: account/login, blog/list, etc. The strategy performs string marching.

Finishing routes are matched by exact string equals operation, intermediate routes are matched with startswith string operation.

Regex Route

Any valid regular expression will match this strategy. However there few limitation that applies if you would like to build paths by name (reverse function to path matching). Use regex syntax only inside named groups, create them as much as necessary. The path build strategy simply replaces named groups with values supplied. Optional named groups are supported.

Curly Route

This is just a simplified version of regex routes. Curly route is something that match the following regular expression:

You define a named group by using curly brakets. The form of curly expression (pattern is optional and corresponds to segment by default):


The curly expression abc/{id} is convered into regex abc/(?P<id>[^/]+).

The name inside curly expression can be constrained with the following patterns:

  • i, int, number, digits - one or more digits
  • w, word - one or more word characters
  • s, segment, part - everything until '/' (path segment)
  • *, a, any, rest - match anything

Note that if pattern constraint doesn't corresponds to anything mentioned above than it is interpreted as a regular expression:

locale:(en|ru)}/home => (?P<locale>(en|ru))/home

Curly route also supports optional values (these should be taken into square brackets):

[{locale:(en|ru)}/]home => ((?P<locale>(en|ru))/)?home

Here are examples of valid expressions:


You can extend recognized curly patterns:

from wheezy.routing.curly import patterns

patterns['w'] = r'\w+'

This way you can add your custom patterns.

Building Paths

Once you have defined routes you can build paths from them. See :ref:`named` how the name of url mapping is cunstructed. Here is a example from :ref:`server time`:

You can pass optional values (kwargs argument) that will be used to replace named groups of the path matching pattern:

>>> r = RegexRoute(
...     r'abc/(?P<month>\d+)/(?P<day>\d+)',
...     kwargs=dict(month=1, day=1)
... )
>>> r.path_for(dict(month=6, day=9))
>>> r.path_for(dict(month=6))
>>> r.path_for()

Values passed to :py:meth:`~wheezy.routing.router.PathRouter.path_for` method override any values used during initialization of url mapping.

:py:class:`KeyError` is raised in case you try to build a path that doesn't exist or insufficient arguments for building a path.