17.1. CherryPy URL Parsing
CherryPy has a special place in the TurboGears frameworkit handles incoming requests and ultimately sends the response back to the user. The first thing CherryPy does is parse out the incoming request object into its component parts and stuffs them into the request object. It then takes the path of the incoming request and tries to match it up to the methods of your application's root class.
In practice, this is straightforward. But the underlying rules can seem a bit complex the first time through. So, we take care of those rules, and then look at some examples that will probably clear things up. Normally, CherryPy looks for the best match (the one that matches the highest number of path elements) and calls the last callable in the hierarchy that it matches. Any "leftover" path elements at the end of the path are turned into positional prarameters and passed into the object that gets called.
The last matching object can be a method, a function, or anything that implements the _call_ method. In Python these objects are often referred to as a "callable" because they can be called with arguments, and they return a value of some kind.
On the surface, that sounds simple enough, but there are a couple of twists and turns that can cause you trouble if you aren't careful. In Python, a class is a callable, which returns an instance. But classes don't return values that can be published to the web when they are called; they return new instances. So, CherryPy introduces a special method index.
CherryPy calls index whenever the last matching object in the hierarchy has an index methodand there are no further path elements in the URL. So, when you have an object with an index method, CherryPy calls that index method rather than calling the object directly. This is roughly equivalent to the way that index.html is served up automatically when you go to a web directory without asking for a specific file. For example, in the Fast Track code, the root controller has a line:
dashboard = DashboardController()
After this has been defined, browsing to /dashboard or /dashboard/ will call the index method of the DashboardController class.
On the other hand, if the last callable object does not contain an index method, it is called directly.
But, wait, that's not all. The index method is only called when the URL maps directly to the last object with nothing "left over." The index method never receives positional parameters.
This brings us to the next "special" methoddefault. If you don't end up calling a class directly, but you didn't define a matching method or function attribute in that class, CherryPy looks for default and calls it if it exists. Unlike index, default gets all the remaining path elements as positional parameters.