Routing System // Werkzeug Documentation

# Werkzeug

The Swiss Army Knife For Python Web Developers

## Routing System

When it comes to combining multiple controller or view functions (however you want to call them), you need a dispatcher. A simple way would be applying regular expression tests on `PATH_INFO` and call registered callback functions that return the value.

Werkzeug provides a much more powerful system, similar to Routes. All the objects mentioned on this page must be imported from werkzeug.routing, not from werkzeug!

### Quickstart

Here a simple example which could be the URL definition for a blog:

    from werkzeug.routing import Map, Rule, NotFound, RequestRedirect

    url_map = Map([
        Rule('/', endpoint='blog/index'),
        Rule('/<int:year>/', endpoint='blog/archive'),
        Rule('/<int:year>/<int:month>/', endpoint='blog/archive'),
        Rule('/<int:year>/<int:month>/<int:day>/', endpoint='blog/archive'),
        Rule('/<int:year>/<int:month>/<int:day>/<slug>',
             endpoint='blog/show_post'),
        Rule('/about', endpoint='blog/about_me'),
        Rule('/feeds/', endpoint='blog/feeds'),
        Rule('/feeds/<feed_name>.rss', endpoint='blog/show_feed')
    ])

    def application(environ, start_response):
        urls = url_map.bind_to_environ(environ)
        try:
            endpoint, args = urls.match()
        except HTTPException, e:
            return e(environ, start_response)
        start_response('200 OK', [('Content-Type', 'text/plain')])
        return ['Rule points to %r with arguments %r' % (endpoint, args)]

So what does that do? First of all we create a new Map which stores a bunch of URL rules. Then we pass it a list of Rule objects.

Each Rule object is instantiated with a string that represents a rule and an endpoint which will be the alias for what view the rule represents. Multiple rules can have the same endpoint but should have different arguments to allow URL construction.

The format for the URL rules is straightforward, but explained in detail below.

Inside the WSGI application we bind the url_map to the current request which will return a new MapAdapter. This url_map adapter can then be used to match or build domains for the current request.

The match method can then either return a tuple in the form `(endpoint, args)` or raise one of the three exceptions NotFound, MethodNotAllowed, or RequestRedirect. For more details about those exceptions have a look at the documentation of the match method.

### Rule Format

Rule strings basically are just normal URL paths with placeholders in the format `<converter(arguments):name>`, where converter and the arguments are optional. If no converter is defined, the default converter is used (which means string in the normal configuration).

URL rules that end with a slash are branch URLs, others are leaves. If you have strict_slashes enabled (which is the default), all branch URLs that are visited without a trailing slash will trigger a redirect to the same URL with that slash appended.

The list of converters can be extended, the default converters are explained below.

### Builtin Converters

Here a list of converters that come with Werkzeug:

string

  This converter is the default converter and accepts any string but only one one path segment. Thus the string can not include a slash.

  Supported arguments:

  - minlength - the minimum length of the string. must be greater than 1.
  - maxlength - the maximum length of the string.
  - length - the exact length of that string.
path
  Like the default string converter, but it also matches slashes.
any

  Matches one of the items provided. Items can either be Python identifiers or unicode strings:

      Rule('/<any(about, help, imprint, u"class"):page_name>')

int

  This converter only accepts integer values:

      Rule('/page/<int:page>')

  Supported arguments:

  - fixed_digits - the number of fixed digits in the URL. If you set this to `4` for example, the application will only match if the url looks like `/0001/`. The default is variable length.
  - min - the minimal value.
  - max - the maximal value.
float

  This converter only accepts floating point values:

      Rule('/probability/<float:probability>')

  Supported arguments:

  - min - the minimal value.
  - max - the maximal value.

Important

Werkzeug evaluates converter arguments as if they are Python method calls. Thus, you should never create rules from user submitted data since they could insert arbitrary Python code in the parameters part.

As a matter of fact this is a legal definition and sets fixed_digits to 2:

    url_map = Map([
        Rule('/picture/<int(fixed_digits=1 + 1):id>.png',
             endpoint='view_image')
    ])

However, evaluating Python expressions is currently an implementation detail and might be unavailable in the future.

### Maps, Rules and Adapters

class Map

  The map class stores all the URL rules and some configuration parameters. Some of the configuration values are only stored on the Map instance since those affect all rules, others are just defaults and can be overridden for each rule. Note that you have to specify all arguments beside the rules as keywords arguments!

  __init__ `(rules=None, default_subdomain='', charset='utf-8', strict_slashes=True, redirect_defaults=True, converters=None, sort_parameters=False, sort_key=None)`

    Initializes the new URL map.

    new in Werkzeug 0.5 sort_parameters and sort_key was added.

    Parameters

      rules: sequence of url rules for this map.

      default_subdomain: The default subdomain for rules without a subdomain defined.

      charset: charset of the url. defaults to `"utf-8"`

      strict_slashes: Take care of trailing slashes.

      redirect_defaults: This will redirect to the default rule if it wasn’t visited that way. This helps creating unique URLs.

      converters: A dict of converters that adds additional converters to the list of converters. If you redefine one converter this will override the original one.

      sort_parameters: If set to True the url parameters are sorted. See url_encode for more details.

      sort_key: The sort key function for url_encode.

  is_endpoint_expecting `(endpoint, *arguments)`
    Iterate over all rules and check if the endpoint expects the arguments provided. This is for example useful if you have some URLs that expect a language code and others that do not and you want to wrap the builder a bit so that the current language code is automatically added if not provided but endpoints expect it.
  iter_rules `(endpoint=None)`
    Iterate over all rules or the rules of an endpoint.
  add `(rulefactory)`
    Add a new rule or factory to the map and bind it. Requires that the rule is not bound to another map.
  bind `(server_name, script_name=None, subdomain=None, url_scheme='http', default_method='GET', path_info=None)`

    Return a new MapAdapter with the details specified to the call. Note that script_name will default to `'/'` if not further specified or None. The server_name at least is a requirement because the HTTP RFC requires absolute URLs for redirects and so all redirect exceptions raised by Werkzeug will contain the full canonical URL.

    If no path_info is passed to match() it will use the default path info passed to bind. While this doesn’t really make sense for manual bind calls, it’s useful if you bind a map to a WSGI environment which already contains the path info.

    subdomain will default to the default_subdomain for this map if no defined. If there is no default_subdomain you cannot use the subdomain feature.

  bind_to_environ `(environ, server_name=None, subdomain=None, calculate_subdomain=False)`

    Like bind but you can pass it an WSGI environment and it will fetch the information from that directory. Note that because of limitations in the protocol there is no way to get the current subdomain and real server_name from the environment. If you don’t provide it, Werkzeug will use SERVER_NAME and SERVER_PORT (or HTTP_HOST if provided) as used server_name with disabled subdomain feature.

    If subdomain is None but an environment and a server name is provided it will calculate the current subdomain automatically. Example: server_name is `'example.com'` and the SERVER_NAME in the wsgi environ is `'staging.dev.example.com'` the calculated subdomain will be `'staging.dev'`.

    If the object passed as environ as an environ attribute, the value of this attribute is used instead. This allows you to pass request objects. Additionally PATH_INFO added as a default ot the MapAdapter so that you don’t have to pass the path info to the match method.

class MapAdapter

  Retured by Map.bind or Map.bind_to_environ and does the URL matching and building based on runtime information.

  match `(path_info=None, method=None)`

    The usage is simple: you just pass the match method the current path info as well as the method (which defaults to GET). The following things can then happen:

    - you receive a NotFound exception that indicates that no URL is matching. A NotFound exception is also a WSGI application you can call to get a default page not found page (happens to be the same object as werkzeug.exceptions.NotFound)
    - you receive a MethodNotAllowed exception that indicates that there is a match for this URL but non for the current request method. This is useful for RESTful applications.
    - you receive a RequestRedirect exception with a new_url attribute. This exception is used to notify you about a request Werkzeug requests by your WSGI application. This is for example the case if you request `/foo` although the correct URL is `/foo/` You can use the RequestRedirect instance as response-like object similar to all other subclasses of HTTPException.
    - you get a tuple in the form `(endpoint, arguments)` when there is a match.

    If the path info is not passed to the match method the default path info of the map is used (defaults to the root URL if not defined explicitly).

    All of the exceptions raised are subclasses of HTTPException so they can be used as WSGI responses. The will all render generic error or redirect pages.

    Here is a small example for matching:

        >>> from werkzeug.routing import Map, Rule
        >>> m = Map([
        ...     Rule('/', endpoint='index'),
        ...     Rule('/downloads/', endpoint='downloads/index'),
        ...     Rule('/downloads/<int:id>', endpoint='downloads/show')
        ... ])
        >>> urls = m.bind("example.com", "/")
        >>> urls.match("/", "GET")
        ('index', {})
        >>> urls.match("/downloads/42")
        ('downloads/show', {'id': 42})

    And here is what happens on redirect and missing URLs:

        >>> urls.match("/downloads")
        Traceback (most recent call last):
          ...
        werkzeug.routing.RequestRedirect: http://example.com/downloads/
        >>> urls.match("/missing")
        Traceback (most recent call last):
          ...
        werkzeug.routing.NotFound: /missing

  test `(path_info=None, method=None)`
    Test if a rule would match. Works like match but returns True if the URL matches, or False if it does not exist.
  dispatch `(view_func, path_info=None, method=None, catch_http_exceptions=False)`

    Does the complete dispatching process. view_func is called with the endpoint and a dict with the values for the view. It should look up the view function, call it, and return a response object or WSGI application. http exceptions are not catched by default so that applications can display nicer error messages by just catching them by hand. If you want to stick with the default error messages you can pass it `catch_http_exceptions=True` and it will catch the http exceptions.

    Here a small example for the dispatch usage:

        from werkzeug import Request, Response, responder
        from werkzeug.routing import Map, Rule

        def on_index(request):
            return Response('Hello from the index')

        url_map = Map([Rule('/', endpoint='index')])
        views = {'index': on_index}

        @responder
        def application(environ, start_response):
            request = Request(environ)
            urls = url_map.bind_to_environ(environ)
            return urls.dispatch(lambda e, v: views[e](request, **v),
                                 catch_http_exceptions=True)

    Keep in mind that this method might return exception objects too, so use Response.force_type to get a response object.

  build `(endpoint, values=None, method=None, force_external=False)`

    Building URLs works pretty much the other way round. Instead of match you call build and pass it the endpoint and a dict of arguments for the placeholders.

    The build function also accepts an argument called force_external which, if you set it to True will force external URLs. Per default external URLs (include the server name) will only be used if the target URL is on a different subdomain.

    With the same map as in the example above this code generates some target URLs:

        >>> urls.build("index", {})
        '/'
        >>> urls.build("downloads/show", {'id': 42})
        '/downloads/42'
        >>> urls.build("downloads/show", {'id': 42}, force_external=True)
        'http://example.com/downloads/42'

    Because URLs cannot contain non ASCII data you will always get bytestrings back. Non ASCII characters are urlencoded with the charset defined on the map instance.

    Additional values are converted to unicode and appended to the URL as URL querystring parameters:

        >>> urls.build("index", {'q': 'My Searchstring'})
        '/?q=My+Searchstring'

    If a rule does not exist when building a BuildError exception is raised.

    The build method accepts an argument called method which allows you to specify the method you want to have an URL builded for if you have different methods for the same endpoint specified.

class Rule

  A Rule represents one URL pattern. There are some options for Rule that change the way it behaves and are passed to the Rule constructor. Note that beside the rule-string all arguments must be keyword arguments in order to not break the application on Werkzeug upgrades.

  string

    Rule strings basically are just normal URL paths with placeholders in the format `<converter(arguments):name>` where the converter and the arguments are optional. If no converter is defined the default converter is used which means string in the normal configuration.

    URL rules that end with a slash are branch URLs, others are leaves. If you have strict_slashes enabled (which is the default), all branch URLs that are matched without a trailing slash will trigger a redirect to the same URL with the missing slash appended.

    The converters are defined on the Map.

  endpoint
    The endpoint for this rule. This can be anything. A reference to a function, a string, a number etc. The preferred way is using a string as because the endpoint is used for URL generation.
  defaults

    An optional dict with defaults for other rules with the same endpoint. This is a bit tricky but useful if you want to have unique URLs:

        url_map = Map([
            Rule('/all/', defaults={'page': 1}, endpoint='all_entries'),
            Rule('/all/page/<int:page>', endpoint='all_entries')
        ])

    If a user now visits `http://example.com/all/page/1` he will be redirected to `http://example.com/all/`. If redirect_defaults is disabled on the Map instance this will only affect the URL generation.

  subdomain

    The subdomain rule string for this rule. If not specified the rule only matches for the default_subdomain of the map. If the map is not bound to a subdomain this feature is disabled.

    Can be useful if you want to have user profiles on different subdomains and all subdomains are forwarded to your application:

        url_map = Map([
            Rule('/', subdomain='<username>', endpoint='user/homepage'),
            Rule('/stats', subdomain='<username>', endpoint='user/stats')
        ])

  methods
    A sequence of http methods this rule applies to. If not specified, all methods are allowed. For example this can be useful if you want different endpoints for POST and GET. If methods are defined and the path matches but the method matched against is not in this list or in the list of another rule for that path the error raised is of the type MethodNotAllowed rather than NotFound.
  strict_slashes
    Override the Map setting for strict_slashes only for this rule. If not specified the Map setting is used.
  build_only
    Set this to true and the rule will never match but will create a URL that can be build. This is useful if you have resources on a subdomain or folder that are not handled by the WSGI application (like static data)
  redirect_to

    If given this must be either a string or callable. In case of a callable it’s called with the url adapter that triggered the match and the values of the URL as keyword arguments and has to return the target for the redirect, otherwise it has to be a string with placeholders in rule syntax:

        def foo_with_slug(adapter, id):
            # ask the database for the slug for the old id.  this of
            # course has nothing to do with werkzeug.
            return 'foo/' + Foo.get_slug_for_id(id)

        url_map = Map([
            Rule('/foo/<slug>', endpoint='foo'),
            Rule('/some/old/url/<slug>', redirect_to='foo/<slug>'),
            Rule('/other/old/url/<int:id>', redirect_to=foo_with_slug)
        ])

    When the rule is matched the routing system will raise a RequestRedirect exception with the target for the redirect.

    Keep in mind that the URL will be joined against the URL root of the script so don’t use a leading slash on the target URL unless you really mean root of that domain.

  empty `()`
    Return an unbound copy of this rule. This can be useful if you want to reuse an already bound URL for another map.
  bind `(map)`
    Bind the url to a map and create a regular expression based on the information from the rule itself and the defaults from the map.

### Rule Factories

class RuleFactory

  As soon as you have more complex URL setups it’s a good idea to use rule factories to avoid repetitive tasks. Some of them are builtin, others can be added by subclassing RuleFactory and overriding get_rules.

  get_rules `(map)`
    Subclasses of RuleFactory have to override this method and return an iterable of rules.

class Subdomain

  All URLs provided by this factory have the subdomain set to a specific domain. For example if you want to use the subdomain for the current language this can be a good setup:

      url_map = Map([
          Rule('/', endpoint='#select_language'),
          Subdomain('<string(length=2):lang_code>', [
              Rule('/', endpoint='index'),
              Rule('/about', endpoint='about'),
              Rule('/help', endpoint='help')
          ])
      ])

  All the rules except of the `'#select_language'` endpoint will now listen on a two letter long subdomain that helds the language code for the current request.

class Submount

  Like Subdomain but prefixes the URL rule with a given string:

      url_map = Map([
          Rule('/', endpoint='index'),
          Submount('/blog', [
              Rule('/', endpoint='blog/index'),
              Rule('/entry/<entry_slug>', endpoint='blog/show')
          ])
      ])

  Now the rule `'blog/show'` matches `/blog/entry/<entry_slug>`.

class EndpointPrefix

  Prefixes all endpoints (which must be strings for this factory) with another string. This can be useful for sub applications:

      url_map = Map([
          Rule('/', endpoint='index'),
          EndpointPrefix('blog/', [Submount('/blog', [
              Rule('/', endpoint='index'),
              Rule('/entry/<entry_slug>', endpoint='show')
          ])])
      ])

### Rule Templates

class RuleTemplate

  Returns copies of the rules wrapped and expands string templates in the endpoint, rule, defaults or subdomain sections.

  Here a small example for such a rule template:

      from werkzeug.routing import Map, Rule, RuleTemplate

      resource = RuleTemplate([
          Rule('/$name/', endpoint='$name.list'),
          Rule('/$name/<int:id>', endpoint='$name.show')
      ])

      url_map = Map([resource(name='user'), resource(name='page')])

  When a rule template is called the keyword arguments are used to replace the placeholders in all the string parameters.

### Custom Converters

You can easily add custom converters. The only thing you have to do is to subclass BaseConverter and pass that new converter to the url_map. A converter has to provide two public methods: to_python and to_url, as well as a member that represents a regular expression. Here is a small example:

    from random import randrange
    from werkzeug.routing import Rule, Map, BaseConverter, ValidationError

    class BooleanConverter(BaseConverter):

        def __init__(self, url_map, randomify=False):
            super(BooleanConverter, self).__init__(url_map)
            self.randomify = randomify
            self.regex = '(?:yes|no|maybe)'

        def to_python(self, value):
            if value == 'maybe':
                if self.randomify:
                    return not randrange(2)
                raise ValidationError()
            return value == 'yes'

        def to_url(self, value):
            return value and 'yes' or 'no'

    url_map = Map([
        Rule('/vote/<bool:werkzeug_rocks>', endpoint='vote'),
        Rule('/vote/<bool(randomify=True):foo>', endpoint='foo')
    ], converters={'bool': BooleanConverter})

If you want that converter to be the default converter, name it `'default'`.