Routes 1.1 Released 4
I’ve released Routes 1.1 today after extending the unit tests for the new Groupings syntax and updating the docs.
The new syntax is quite powerful and will hopefully make everyone using Routes rather happy. While I’m not about to encourage anyone to use URL’s with .html at the end, there’s plenty of times when you want extensions to mingle with dynamic parts. You can also get some useful abilities like being able to pull out the extension like so:
map.connect('archives/:category/:(section).:(format)', controller='archive', action='by_extension')
This makes it easy to toggle the response depending on the extension, and the regexp business is handled for you.
Integration Enhancements
An additional feature, suggested by a Routes user was to make integration easier in WSGI environments. Earlier, at the beginning of each request you would have to populate the Routes config with the host, protocol, and match result. Now, merely passing the WSGI environ to the Routes config object will run a match, and populate those attributes for you.
The Routes Mapper now can take a function that when called returns a list of valid controllers. If you want to use the directory scanner Routes comes with, all you need to do is pass in the directory you’d like to scan and Routes will scan it for you.
These two new integration improvements make it rather simple to integrate Routes, here’s a basic WSGI app showing this off:
#myapp.py
from routes import *
map = Mapper(directory='/my/directory/of/controllers')
map.connect(':controller/:action/:id')
map.connect('home', '', controller='home', action='splash')
class WSGIApp(object):
def __init__(self, mapper=map):
self.mapper = mapper
def __call__(self, environ, start_response):
config = request_config()
config.mapper = self.mapper
config.environ = environ
if not config.mapper_dict:
start_response("404 Not Found", [("content-type","text/html")])
return ["No match"]
else:
start_response("200 OK", [("content-type","text/html")])
return ["Match with the following dict: %s" % str(config.mapper_dict)]
That’s it! If you’re not using WSGI, there’s been no backwards breakage so the old style of setting up all the attributes of the config will work fine as well.
So, now I have to figure out if there’s anything else Routes should possibly have… or is the only space for improvement at this point further optimization and perhaps usability improvements?






How do you suggest handling http verbs (GET, POST, PUT, DELETE) for a Rest style application using Routes?
Assume using WSGI.
Currently it looks like you need to either
a) create 1 map per verb and then check the appropriate map for the verb for this request.
b) have a switch in the controller by verb, but then you are passing to the controller urls that should have generated a 404: ie messy.
I would like to have 2 features
i) specify which verbs should match this route (default to GET only)
ii) allow the verb to be attached to the action name. So GET and POST result in different actions within the same controller GET_action and POST_action
The combination of these two mean that I can use a single connect to have the same url call different actions for GET and POST while not accepting PUT and DELETE.
Hi, Has anybody made an attempt to use Routes with twisted.web2? There should be a way to map ‘routes’ using child_* feature of the twisted.web2 Object Traversal machinery.
Many people think WSGI will replace mod_scgi and all the other webserver adapters. This is partly due to the confident language in the PEP about connecting to “web servers”. But both sides of WSGI must be in the same process, for the simple reason that the spec requires an open file object in the dictionary, and you can’t pickle a file object and transmit it to another process. So a WSGI call from an Apache module to an embedded Python application is possible, but a WSGI call from Apache to a long-running application server is not. Yet these long-running servers are necessary to maintain state and factor out the initialization overhead. SCGI can replace the framework-specific adapters since it is serializable and framework neutral (and programming-language neutral), but WSGI will have to operate on the “application side” of an SCGI interface.
Actually, no one using WSGI thinks it will replace the other adapters. In fact, the deployment guides for WSGI apps say to use SCGI, Fast CGI, or AJP.
WSGI was originally made so that you could write a single WSGI server/gateway for one of those protocols that would work with any WSGI application. Originally, every Python web framework needed its own special wrapper, which led to a ton of redundant work so that all the various frameworks could work with the various adaptors.