Intro to TurboGears for CakePHP developers


This document serves as an intro to TurboGears for those migrating from CakePHP (and possibly other PHP frameworks). We will assume some familiarity with the Python language, and will try to stick to outlining the core differences between the frameworks rather than the languages (quite beyond the scope of this document).

A 30,000 Feet Comparison

Of course, the largest difference between CakePHP and TurboGears is the core language. However, from a technical standpoint, both are quite similar: Both are open source, both have an active community, and both provide a rich component set.

Framework Language License Started Deployment Options MVC MVC Push/Pull i18n & l10n
CakePHP PHP MIT 2005 Apache, FastCGI, etc. Yes Push Yes
TurboGears Python MIT/LGPL 2005 paster, Apache (mod_wsgi or mod_proxy) Yes Push Yes

Feature and component wise, both frameworks provide advanced functionality such as a rich ORM, a tight security framework, and an easy to use forms creation & validation framework:

Feature/Component CakePHP TurboGears
ORM: Active Record Pattern SQLAlchemy (Data Mapper Pattern)
Testing Framework: Based on SimpleTest nose
Security Framework: Security component repoze.who & repoze.what
Forms Framework: Form helper tw.forms & formencode
Caching Framework: Yes beaker
DB Migration Framework: SchemaShell sqlalchemy-migrate
Template Framework: PHP files Multiple [1]
Ajax: Prototype & toscawidgets or roll your own [2]
[1]TurboGears supports Genshi (default), Mako, and Jinja2 out of the box. See the alternate templates page for more information.
[2]TurboGears is JavaScript/Ajax agnostic and therefore approaches Ajax and DHTML differently than a framework tied to only one JS library. For more information see the ToscaWidgets section.

Project Folders

CakePHP TurboGears
app/config myapp/config
app/controllers myapp/controllers
app/locale myapp/i18n
app/models myapp/model
app/plugins myapp/lib
app/tmp data
app/vendors n/a – use easy_install packagename
app/views myapp/templates
app/webroot myapp/public

See this image for more information.


By default TurboGears is setup with one default route which goes to your RootController. This means you typically don’t have to think about routes at all, and gives you great design flexibility.

However, advanced routing is available if needed. See Routes Integration in TG2 for more information.


In CakePHP (and many other PHP web frameworks) you are expected to have a separate controller file & class for each :controller route. The methods of the controller class become the :action routes, with the method arguments being the :id.

In TurboGears, the philosiphy is similar with a bit of added flexability. As was mentioned in the previous section, the default routing in TurboGears is to the RootController class in myapp/controllers/ From RootController, you are free to define “sub-controllers” and methods however you like. A typical setup might look like this:

In myapp/controllers/

# initial imports edited out

# this import loads our "sub-controller"
from myapp.controllers.about import AboutController

class RootController(BaseController):
    # the line below instructs the "about" route ( to
    # load the index method of the AboutController
    about = AboutController()

    # the next few lines handle the loading of the "root" route (
    @expose('myapp.templates.index') # loads the index template
    def index(self):                 # defines the "index" action
        return dict(page='index')    # the 'page' variable is available in our template

    # you could just as easily specify another "controller" route (like we did with 'about')
    # by defining another method in this controller (becomes
    @expose()                        # no template needed (returning a string)
    def contact(self):
        return ''   # simply prints

This is what the AboutController file might look like:

In myapp/controllers/

class AboutController(BaseController):
    # the index action (
    def index(self):
        return dict(page='about')

$components, $helpers, and $uses

Although these attributes play a major part in CakePHP classes, TurboGears has no need for this type of class attribute definition. To use a “component” or “helper” package in your class you would simply import packagename. For your models you would simply from myapp.model import ModelClassName.

Controller Methods

CakePHP has a few special controller methods that deal with things like passing objects to a template, rendering templates, etc. Below is a list of these methods, and TurboGears’ equivalent:

CakePHP TurboGears
set() tmpl_context or passed in return dict()
render() @expose(
redirect() from tg import redirect
flash() from tg import flash


The “batteries included” nature of Python (and therefore TurboGears) means that you have a lot of packages available right at your fingertips. Aside from familiarizing yourself with Python’s standard library, it is also a good idea to become acquainted with TurboGears’ module library.

A Comparison of Components

CakePHP [3] TurboGears
ACL, Auth & Security repoze.who and repoze.what
Cookie from tg import response, response.set_cookie() & from tg import request, request.cookies
Email TurboMail [4]
RequestHandler request.environ (dictionary)
Session from tg import session

Models & Behaviors

TurboGears uses a high-performance enterprise-level SQL toolkit and ORM named SQLAlchemy.


Whereas PHP itself acts as CakePHP’s template language, TurboGears has a number of templating languages available. The most popular choices are Genshi (a pure XML-based template language) and Mako (non-XML, but much faster than Genshi).

As we saw earlier in TG’s equivalent Controller Methods, data is typically passed from the controller to the view by using the special tmpl_context object, or by defining dictionary values in the controller method’s return.


Helpers are managed in the mypackage/lib/ file and are typically accessed in your template through the h object. TurboGears ships with several built-in helpers (see the webhelpers page), but Python’s modular nature makes it very easy to add helpers to your project. Usually all you have to do is easy_install packagename and then at the top of your file put import packagename as mynewhelper. You can then access your new helper in your view by using h.mynewhelper.

A Comparison of Helpers

As we just mentioned, TurboGears makes it very easy to “plug & play” helpers. Below is a list of CakePHP’s built-in helpers, with the TurboGears equivalent that is typically used:

CakePHP [5] TurboGears
Ajax toscawidgets or roll your own [2]
Cache beaker
Form tw.forms and/or sprox
HTML webhelpers.html
JavaScript webhelpers.html
Number webhelpers.number
Paginator webhelpers.paginate
RSS webhelpers.feedgenerator
Session tg.session
Text webhelpers.text
XML ElementTree or lxml


Apart from a project quickstart, TurboGears tries to avoid generating code for you. We are of the opinion that it is easier to build pages from the ground up than to tweak code that is generated from a framework’s “best-guess” about your project.

Having said that, there are a couple of modules and extensions that can help you start interacting with your models right away:

Pros and Cons


  • PHP hosting environments are a dime a dozen
  • The “views” are regular PHP files (no need to learn a new template syntax)
  • The built-in $ajax helper class provides a convenient wrapper for Prototype/Scriptaculous
  • The built-in DHTML & Ajax is tied to one JavaScript/Ajax library
  • CakePHP is typically much slower than TurboGears [curiasolutions]


  • SQLAlchemy
  • JavaScript library independent with multiple widget options
  • Multiple templating options (XML based and non-XML based)
  • TurboGears is typically much faster than CakePHP [curiasolutions]
  • Might need root access to set up a “production” environment (see deployment options)