In response to my previous post, someone asked “… what’s the point? How one way is better than the other?” My response was that I’m “not trying to judge these frameworks from the perspective of a developer (at least not completely), but rather from the POV of ‘if I were writing a framework, which features are essential, which nice to have, which I can disregard'” (emphasis added). Of course, I have my own biases as a developer as to what I consider “nice” or essential.
With that clarification out of the way, let’s look at the next feature: the WSGI callable generally known as the application object.
Django doesn’t want developers to be concerned with this artifact. A Django application is the collection of model, views (controllers in standard MVC terminology) and templates (views) that gets run by the server. For those interested, the Django WSGI callable is an instance of WSGIHandler (in django.core.handlers.wsgi).
As best as I can tell, Twisted Web expects the developer to write the application object. It will get called from the WSGIResponse run() method in twisted.web.wsgi. As its documentation says, Twisted Web is “a framework for doing things with the web” but is “not a ‘web framework’ in the same sense” as Django, so it doesn’t fit well in this comparison.
Pyramid‘s Router class (in pyramid.router) is what implements the WSGI callable. The Router instance gets created from the Configurator class’s make_wsgi_app() method. Select Router attributes and methods:
- registry (from args)
In CherryPy, the Application class is the application object, although it’s not generallly used directly. Instead a user root object is mounted on a Tree which is a registry of these applications. Major attributes and methods:
- root (from args): root object (application handler)
- namespaces, config: for configuration
- wsgiapp(): a CPWSGIApp instance, to handle apps in a pipeline
Being a support library, Werkzeug doesn’t include an application object, but it has a sample in its Shortly example. Major attributes and methods:
- dispatch_request(): dispatcher
- jinja_env: template enviroment
- url_map: Map() taking list of Rule()’s
- error_404(): error handler
- render_template(): template renderer
Like Django, Web2py isn’t interested in having developers worry about the application object. Its WSGI callable is the standalone wsgibase() function, in gluon.main.
The web.py application class (yes, not capitalized) implements its WSGI callable. Major attributes and methods:
- autoreload (from args)
- init_mapping (from args)
- handle(): matches path to mapping
- run(): runs the developer server
- notfound(), internalerror(): error handlers
Flask‘s Flask class is its application object, derived from flask.helpers._PackageBoundObject. Selected attributes and methods (in addition to those in Werkzeug’s example above):
- static_url_path, static_folder (from args)
- instance_path (from args or auto-determined)
- before/after_xxx_funcs (dicts)
- route(): decorator for URL rules
- error_handler_spec (a dict)
- errorhandler(): decorator for error handler functions
Like Werkzeug, WebOb doesn’t include an application object, but it has a sample in its wiki example, most of it very specific to the example.
Bottle‘s Bottle class is its WSGI callable. Major attributes and methods:
- routes (list) and router (class Router instance)
- config (class ConfigDict instance)
- mount(): to mount an app at a given point
- match(): to search for matching routes
- route(): decorator to bind a function to a URL
Pesto‘s DispatcherApp class is its application object. Major attributes and methods:
- prefix (from args): a “mount” point
- matchpattern(), match(): matches URLs (match is decorator)
- urlfor(): handler/dispatcher to URL converter
- gettarget(): returns a four-part tuple from the URI
- status404_application(): error handler
Diva‘s Application class is the object of interest. Select attributes and methods:
- config (from kwargs), configure()
- routing_cfg and routing
- locale_dir (from args)
- template_dirs (from args)
- templates(): template loader
- prepare() and cleanup(): before and after methods
Summary: For developers who care about writing application code, Django and Web2py and to some extent Pyramid and CherryPy hide the existence of the WSGI callable, while other frameworks require that the programmer instantiate it or invoke it. If I were to write a framework, I’d want to make it easy on the developer as the former projects do, but wouldn’t keep it completely out of sight.