I’ve noticed three main ways Python web frameworks deal request handing: decorators, controller classes with methods for individual requests, and request classes with methods for GET/POST.
I’m curious about the virtues of these three approaches. Are there major advantages or disadvantages to any of these approaches? To fix ideas, here are three examples.
Bottle uses decorators:
@route('/')
def index():
return 'Hello World!'
Pylons uses controller classes:
class HelloController(BaseController):
def index(self):
return 'Hello World'
Tornado uses request handler classes with methods for types:
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")
Which style is the best practice?
There’s actually a reason for each of the three methods you listed, specific to each project.
simple/straightforward as possible
for the programmer. With decorators
for routes you don’t have to worry
about the developer understanding OOP.
code re-usable and to be easily
integrated with WSGI-style HTTP
process routing. As such, they have
chosen a very OOP way of organizing
routes. As an example, you could
copy & paste HelloController into any
Pylons app and it should just
magically work. Even if said app is
being served up via WSGI in some
complicated fashion.
doing things the way it does:
Tornado’s epoll-based IOLoop (in conjunction with tornado.web.Application)
instantiates each RequestHandler as
requests come in. By keeping each
RequestHandler limited to a specific
GET or POST this allows IOLoop to
quickly instantiate the class,
process the request, and finally let
it get garbage collected. This keeps
it fast and efficient with a small
memory footprint regardless of how
many RequestHandlers your application
has. This is also the reason why Tornado can handle so many more simultaneous requests than other Python-based web servers (each request gets its own instance).
Now, having said all that you should know that you can always override the default framework behavior. For example, I wrote a MethodDispatcher for Tornado that makes it work more like Pylons (well, I had CherryPy in mind when I wrote it). It slows down Tornado a tiny amount (and increases the memory footprint slightly) due to having one large RequestHandler (as opposed to a lot of small ones) but it can reduce the amount of code in your app and make it a little easier to read (In my biased opinion, of course =).