cgi_app: A Framework for Creating MVC Web Applications in Python


This module is a port of Jesse Erlbaum's popular CGI::Application Perl module to python.

It allows you to seperate an application's display and business logic, and reduces many of the tedious aspects of writing CGI applications. See the original CGI::Application documentation for more of an argument for this approach. cgi_app doesn't duplicate every single feature of CGI::Application but it incorporates all the core aspects and has the same basic design.


cgi_app has been tested with python 2.2 and 2.3. It should work with any webserver that provides a normal CGI environment. Specifically, it has been tested on Apache 1.x and 2.x. It should run on any platform that python will run on, but it has only been tested on GNU/Linux. If you want to take advantage of cgi_app's mod_python integration, you'll need to be running mod_python 3.1 or greater (which requires Apache 2.x in turn).

If you want to use the built-in template() method, you need either htmltmpl, or simpleTAL. To use htmltmpl, you'll want to install a patched version of htmltmpl. htmltmpl is a port of Sam Tregar's HTML::Template perl module. My patched version improves htmltmpl's compatability with HTML::Template templates and is fully backwards compatable with previous versions. I expect it to be merged with the official version pretty soon. In the meantime, get the patched version here: (The unpatched version of htmltmpl will work with cgi_app 1.2+ but the included sample templates require the patched version).

simpleTAL should work fine out of the box. It's currently the templating language that the author recommends.

If you prefer another templating system (or none), just override the template() method.


To install, just run:

python install

in the cgi_app directory as root.

Release Notes

1.3 -- 2004-12-06

new features

1.2 -- 2004-03-06

bug fixes

new features


cgi_app is released under the GNU GPL.


The CGI::Application documentation is a good start and will explain the basic ideas behind the architecture. On this page, we'll just go over how cgi_app's specific syntax. Here is a basic usage sample:


from cgi_app import CGI_Application

class Example_App(CGI_Application):
    def setup(self):
        self.start_mode = 'welcome'
    def welcome(self):
        return self.template("welcome.tmpl",{})
    def param_example_form(self):
        return self.template("param_example_form.tmpl",{})
    def param_example(self):
        name = self.param('name')
        return self.template("param_example.tmpl",{'name' : name})
    def cookie_example(self):
        return self.template("cookie_example.tmpl",{})
    def redirect_example(self):

# can be used as a mod_python handler
def handler(req):
    e = Example_App(req)

# or a plain old CGI
if __name__ == "__main__":
    e = Example_App()

You can see this in action here.

The basic idea is that you define a class for your application that subclasses CGI_Application. You define a method for each 'page' of your web application. Runmodes are automatically mapped to methods with the same name. This is different from CGI::Application which requires you to manually configure all the runmode mappings. To map runmodes to methods with different names, you can still override the 'setup()' method and manually add entries to the dispatch table. The run-mode is specified by a CGI parameter ('rm' by default, but you can change it.) to run your application, you just instantiate your class and call its 'run()' method.

Each run mode carries out its function and returns a string which will be sent to the browser. Your run modes should never print anything; let cgi_app take care of all the displaying.

cgi_app wraps around the standard python cgi and Cookie modules, giving you an interface that is more similar to Perl's module.

If you develop an application using cgi_app, the same code can be run as a CGI script or as a mod_python handler. Since CGI can sometimes be easier to debug, this gives you a nice path between development and production environments.

The source code is short and intended to be very readable. If you have any questions that aren't addressed in the documentation below, try reading the source code.

here are some of the available methods:


returns the value of a named CGI parameter. eg,

foo = self.param('foo')

param() will always return a string. If the parameter wasn't specified, it will return an empty string.

if you have multiple parameters with the same name, param() will return an empty string and you will have to access self.form yourself (self.form is a FieldStorage object. see the documentation for the cgi module).


returns the value of a named cookie. eg,

username = self.cookie('username')

cookie() will always return a string. If the cookie wasn't sent by the browser, it will return an empty string.


This method should be overridden. Use it to initialize your application and set up your run mode dispatch table. eg,

    def setup(self):
        self.start_mode = 'welcome'

By default, cgi_app will map runmodes to methods with the same name. To change this behavior, simply add an etry to the _dispatch table in setup. eg,

    def setup(self):
        self.start_mode = 'welcome'
        self._dispatch['foo'] =

Then, runmode 'foo' would trigger a call to the bar() method instead of foo().

You should make sure to set the start_mode to a default value. This specifies the runmode that is specified if no runmode parameter is passed in.


This runs the application. It will look for the run mode parameter, map it to a method, execute that run mode, and send the results along with the proper HTTP headers and cookies to the browser. If it finds an entry for the runmode in the _dispatch table, it will use that, otherwise, it will look for a method with the same name as the runmode.


Override this method if you have any application cleanup that needs to be performed. This method is called automatically at the end of run(). Don't call it yourself.


If you don't want to use 'rm' as the run mode parameter, use this method to set it to a different value:

        a = MyApp()

you'll need to call this method before you call run().


Use this method to change existing HTTP headers (such as 'Content-Type') or to add additional headers. eg,

        self.header_props({'Content-Type' : 'application/xml'})


deprecated. you should use the set_cookie() method now instead. set_cookies() will continue to work for the foreseeable future, but set_cookie() will make your life easier.

Sets cookies. Pass it a list of Cookie objects. eg,

        import Cookie
        c = Cookie.SimpleCookie()
        c["fig"] = "newton"

If you continue to use this method instead of set_cookie(), you won't be able to move between CGI and mod_python transparently. If you are using mod_python, the cookie objects that you pass in need to be mod_python.Cookie objects instead of regular Cookies. eg,:

        from mod_python import Cookie 
        c = Cookie.Cookie("fig","newton")

the set_cookie() method hides this difference for you.


sets a cookie for you. pass in the name, value and any other fields you want to set. 'expires' takes an integer with the number of seconds before the cookie expires. if you don't pass in an 'expires' field, it will expire at the end of the browser session.

doing cookies through this method hides the differences between mod_python's cookies and CGI's cookies so you can more easily switch between the environments.


returns the HTTP_REFERER, doing the right thing in mod_python and CGI environments for you.


If, instead of displaying a page of output, you want to redirect the browser, use this method. Pass it a url.


If you call this and still return a string from your run-mode, the redirect will take precedence and the return value will be ignored.


Uses the htmltmpl library to replace the variables in a template file with variables specified in a dictionary. Returns a string.

        name = "bob"
        age = 23
        return self.template("example.tmpl",{'name' : name, 'age' : age})

with example.tmpl:

        name: <tmpl_var name="name" escape="html"><br />
        age: <tmpl_var name="age" escape="html"><br />

will return:

        name: bob<br />
        age: 23<br />

template() will switch between simpleTAL templates and htmltmpl templates based on the template filename extension. If the template filename ends in ".pt", it will use simpleTAL, otherwise it will use htmltmpl. The template syntax and capabilities differ between the two but this method is called the same in either case. simpleTAL is more complicated but also more powerful; it is currently recommended by the author.

See the htmltmpl or HTML::Template documentation for details on the htmltmpl template syntax and the simpleTAL or TAL documentation for details on simpleTAL's syntax.

By default, it searches for template files in a directory named "templates". You can specify a different directory by setting the object's 'template_dir' attribute to a different value.

When using simpleTAL, it will look for a file called "" in the templates directory. If it finds it, it will read it in and use it as a global site macros file. Macros defined in can be accessed in the templates with the metal:use-macro="sitemacros/macros/yourmacro" syntax.

if you prefer another templating approach, just override this method, or don't use it.

mod_python support

cgi_app 1.2 added support for mod_python. almost everything should be transparent. instead of running the application with

if __name__ == "__main__":
    app = MyApp()

you would do:

def handler(req):
    app = MyApp(req)

note that the request object is passed to the constructor. everything else should work about the same, just faster. if you need to access the request object from a handler for some advanced mod_python trickery, it is available as self.req.

the only thing you might have to be careful about is with cookies. when you pass cookies in with self.set_cookies(), make sure that the cookies are mod_python.Cookie objects and not from the regular Cookie library. If you use the set_cookie() method (introduced in 1.3), it will take care of the differences with cookies for you.

alas, only mod_python 3.1 or greater is supported. ie, mod_python 2.x and mod_python 3.0.x are not supported by cgi_app. i welcome patches.

here's some sample code:


from cgi_app import CGI_Application
from mod_python import apache, Cookie
import time

def handler(req):
    a = App(req)

class App(CGI_Application):
    def setup(self):
        self.start_mode = 'test'

    def test(self):
        foo = self.param('foo')
        return foo

    def redirtest(self):

    def set_cookie_test(self):
        return "cookie set."

    def cookie_test(self):
        prefs = self.cookie('spam')
        return prefs


cgi_app was written by Anders Pearson. Submit bug reports or other feedback to <>. It is based on the design of CGI::Application, written by Jesse Erlbaum and others. It also integrates with htmltmpl, written by Tomas Styblo as a port of Sam Tregar's HTML::Template.