OO, pragmatic design, URL mapping, Django, and CherryPy

by Jeremy Jones

I've been working quite a bit with Django lately. One of the things I really love about Django is its URL mapping and how that ties into the request handling layer (which Django refers to as the "view"). Basically, you define a regex for a URL and associate it with a function to handle matching requests. When a request comes in that matches a URL regex, the request is passed off to the corresponding function in the URL mapping. Notice that I said "function" and not "method". The "view" (as Django refers to it, but what MVC frameworks would probably refer to as the "controller" layer) in Django is basically an event handler. It makes absolute sense for it to be a function rather than a method on some object.

As I've been enjoying the pragmatic design of Django's request mapping and handling, I started thinking back to my experience with CherryPy. In CherryPy, you define a class and certain methods of that class handle requests as they come in. The URL mapping is determined by attributes of an instance of that class, so it's really more implicit than Django's URL mappings are. I guess the two reasons CherryPy uses an OO approach in regard to its "controller" layer (which, CherryPy isn't a full MVC framework, but the term somewhat applies) is 1) this is probably the best way to accomplish URL mapping without having an explicit URL->handler map, and 2) it provides a way to logically structure your code.

After having worked with both URL mapping techniques, I definitely prefer Django. The whole OO approach in this regard just feels wrong to me. Static state for the application as a whole should really be in a config file. Dynamic state for the application should be in a database. And state for each specific user should really be kept in session memory. I'm sure there are legitimate uses for it, but attaching state to the handler object seems really wrong and when you're working with an object, sometimes the temptation is to do just that (self.foo_attribute = some_funky_variable). I'm sure this probably isn't a widespread problem among CherryPy users, I'm just mentioning that the temptation is there. Regarding separation of code, it's really easy to structure modules of functions for logical structuring of code.

I'm not saying that CherryPy is wrong or bad for the decision that it made to use OO for its URL mapping and request handling. I'm just saying that it feels less natural to me than the approach that Django has taken. But I'm also saying that Django feels more natural to me. And this aspect of Django feels more in line with the Zen of Python than the same aspect of CherryPy, specifically "Explicit is better than implicit" and, to a lesser degree, "Flat is better than nested".

I'm sure plenty of you will think I'm dead wrong about this. I welcome the feedback and the dialog.


2006-03-16 02:41:41
I had a short glance at CherryPy and TurboGears and I found it a bit puzzling that all the examples I found seemed to have whole application logic wired directly into the event handler methods in controllers.py. I suppose it makes sense in very small applications and I never found big enough examples to look at how people organize code in reality. I'm not actually familiar with any of the web frameworks so I don't know how Django compares to it.

What I was kind of expecting to find was separate application object(s), not directly built on top of (inheriting) the web framework but instead modeled as state machine that get events dispatched from the event handler methods.

Jeremy Jones
2006-03-16 05:04:04
CherryPy's approach is interesting, definitely. How I read the code is that the application code doesn't inherit from the web framework code; an instance of application code is set to an attribute of the web framework code. So, a "hello, world" from the CherryPy tutorial looks like this:

import cherrypy

class HelloWorld:
def index(self):
return "Hello world!"
index.exposed = True

cherrypy.root = HelloWorld()

So, the application object is set to the attribute "root" on the module object "cherrypy". By design, the logic belongs in the class above, the mapping is implied by method names, and the application code responds to requests that make their way to it.

Django is similar, but quite different. You still have your application logic in the "controller" layer (which Django refers to as "view"). But the mappings are explicit.

In either Django or CherryPy, you could pull the logic out of the "controller" layer and put it into classes if that makes sense, or in various functions in a library or set of libraries.