Saturday, December 10, 2005

Hierarchical CherryPy

Forging ahead on my time tracking web application, I ran into a little problem with CherryPy/TurboGears. Specifically, it has to do with creating hierarchical URL trees that look like "http://.../customers/<customer_id>/". What I'd like to be able to do is something like this:

class Root(controllers.Root):
def __init__(self):

class Customers(controllers.Root):
def lookup(self, custid):
'Some lookup function which will continue traversing the URL'

class Customer(controllers.Root):
def index(self, arg):

For now, I've overridden the __getattr__ method of the "Customers" class to do this, but it looks like TurboGears looks up the root.customers.cust_id about four times per request, so it seems a little inefficient. CherryPy's default method won't work either, because once you hit default, there's no more traversing. I think Quixote has something that handles this, but it's been a while since I looked at it. Any suggestions?

Categories: , , ,


  1. Well, I did at least find the way Quixote does this: by using the _q_lookup() method. It's covered in Quixote tutorial 1.

  2. Anonymous7:57 PM

    I tend to use CherryPy's default method and just handle the rest of the dispatching manually.

  3. robert, thanks for the comment. The reason I can't use default is that I want to have CherryPy continue traversal after the "programmable" part of my path (the <customer id> in the example above). default(), on the other hand, insists on being the last thing on the path. (It handles the rest of the path as positional arguments.) If there was a mechanism to do this, you could basically have nice, dynamic paths. I guess it's kind of Zope-ish. But maybe that's not so bad.

    I'd like to do the "Right" thing in CherryPy, I'm pretty sure overriding __getattr__ is not the Right thing, but I can't figure out a blessed way to do it. Of course, this is just a "wart," in my opinion. Not enough to make me switch to something else.

  4. Anonymous2:07 PM

    I've written a decorator that does this: