Dynamic, framework-neutral metadata describing path/URI structures with text and JSON representations.

For server apps built on Routes-based frameworks (e.g. Pylons), a wsgi middleware component described_routes.routes.DescribedRoutesMiddleware converts and publishes the Routes Mapper structure and adds link headers to facilitate their auto-discovery.

For the client side, see PathTo.


    • Converting to and from JSON and YAML
    • Plain text representation
    • Basic URI and path generation
    • Dynamic partial template expansion
    • Attributes
    • Navigation


Converting to and from JSON and YAML

The ResourceTemplate and ResourceTemplates classes have constructors that can take native Python dicts and lists (of dicts or ResourceTemplate objects), so that converting to and from JSON and YAML is very straightforward. For example (with output edited for brevity and formatting), JSON conversions look like this:

>>> import json
>>> user = ResourceTemplate(json.loads(user_json))
>>> print json.dumps(user.to_py())
  "name": "user",
  "uri_template": "{user_id}{.format}",
  "params": ["user_id"],
  "optional_params": ["format"],
  "options": ["GET", "PUT", "DELETE"],
  "resource_templates": [
      "name": "edit_user",
      "rel": "edit",
      "uri_template": "{user_id}/edit{.format}",
      "params": ["user_id"],
      "optional_params": ["format"],
      "options": ["GET"]
      "name": "user_articles",
      "rel": "articles",
      "uri_template": "{user_id}/articles{.format}",
      "params": ["user_id"],
      "optional_params": ["format"],
      "options": ["GET", "POST"]

This (or something very much like it) should work with your favourite JSON or YAML module.

Plain text representation

ResourceTemplate and ResourceTemplates objects print like this:

>>> print users
users                  users                GET, POST    {.format}
  new_user             new_user             GET          {.format}
  {user_id}            user                 GET, PUT, DELETE{user_id}{.format}
    edit               edit_user            GET          {user_id}/edit{.format}
    articles           user_articles        GET, POST    {user_id}/articles{.format}
      new_user_article new_user_article     GET          {user_id}/articles/new{.format}
      recent           recent_user_articles GET          {user_id}/articles/recent{.format}
      {article_id}     user_article         GET, PUT, DELETE{user_id}/articles/{article_id}{.format}
        edit           edit_user_article    GET          {user_id}/articles/{article_id}/edit{.format}
    profile            user_profile         GET, PUT, DELETE, POST{user_id}/profile{.format}
      edit             edit_user_profile    GET          {user_id}/profile/edit{.format}
      new              new_user_profile     GET          {user_id}/profile/new{.format}

Basic URI and path generation

URIs and paths can be generated for specific resources, given a dict of actual parameters:

>>> actual_params = {"user_id": "dojo", "format": "json"}
>>> users.uri_for(actual_params)
>>> users.path_for(actual_params)

Where the resource template has a path_template but no uri_template, a base parameter may be supplied to the uri_for() method.

Partial template expansion

ResourceTemplate objects can be parameterised as shown below. The effect of this is to define a "mini application" around a concrete resource or set of resources:

>>> actual_params = {"user_id": "dojo", "format": "json"}
>>> print user.partial_expand(actual_params)
user                 user                 GET, PUT, DELETE
  edit               edit_user            GET          
  articles           user_articles        GET, POST    
    new_user_article new_user_article     GET          
    recent           recent_user_articles GET          
    {article_id}     user_article         GET, PUT, DELETE{article_id}.json
      edit           edit_user_article    GET          {article_id}/edit.json
  profile            user_profile         GET, PUT, DELETE, POST
    edit             edit_user_profile    GET          
    new              new_user_profile     GET          


The described_routes.routes module provides integration with Routes, the routing component of Pylons and some other web frameworks.

The make_resource_templates``function will create a ``ResourceTemplates object from a Routes Mapper.

DescribedRoutesMiddleware is a wsgi middleware component that serves ResourceTemplates and ResourceTemplate metadata and decorates regular resources with the link headers that facilitate resource discovery.

DescribedRoutesMiddleware should be placed in the wsgi middleware stack between the RoutesMiddleWare component and the main application. In a Pylons app, the relevant section of config/ should look something like this:

app = PylonsApp()
app = DescribedRoutesMiddleware(app, config[''])
app = RoutesMiddleware(app, config[''])

By default, ResourceTemplates and ResourceTemplate data will be served at /described_routes; this can be overridden with the path parameter. Assuming the default path is retained, data describing the whole application will be served at /described_routes; data describing a resource corresponding to a ResourceTemplate named 'foo' will be served at /described_routes/foo. In both cases, routing parameters may be supplied, resulting in partially expanded templates, e.g. at /described_routes?format=json.

Data will be served in json format if the path has a .json extension, if the Accept header includes 'application/json' or if there is no Accept header at all. Otherwise the tabular plain text format is served.



A ResourceTemplate object has the following attributes:

name:An application-wide identifier
rel:An indication of a child resource's relationship to its parent
path_template:A template for the resource's path, in the style of URI Template but as a relative path
uri_template:A template for the resource's URI (generated only if the root URI is known at generation time)
params:A list of parameters required by path_template
 A list of optional parameters that may be incorporated by the path_template
options:A list of HTTP methods supported by the resource
 A list of ResourceTemplate objects, implemented by the ResourceTemplates class

All attributes are optional; empty or blank attributes are omitted in external representations.

By convention, members of collections identified by key attributes don't have a rel attribute. In the examples above, the user template has children named edit_user and user_articles with rel attributes of "edit" and "articles" respectively, but the user_article child of user_articles has none, as it is identified relative to its parent by an article_id parameter.


These methods support navigation by name or by rel respectively:

1) ResourceTemplates.all_by_name(): this returns a memoized dict of all ResourceTemplate objects in or below the ResourceTemplates collection.

2) ResourceTemplate.find_by_rel(rel): this returns a list of all ResourceTemplate objects that are direct descendants of the target ResourceTemplate and have a rel attribute equal to the one the supplied.


Mike Burrows (asplake), email, website (see articles tagged described_routes)