Bad, vile and meaningless: Building a subway from Alan's clob

Python on Rails: Subway

You get Subway from SVN repository. There is no public release as of yet. This, however, is not as bad as it sounds like because Subway is not as much a framework as it's a combination of other frameworks.

The components that Subway derives from are:

The idea is that Subway is a way of life in web applications. Others usually impose no structure as to the eventual form of your application. Subway however has a clear plan and encourages a particular division of labour in your webapp. In Subway, you shall program in MVC fashion.

Installing Subway

At this moment the subway-paste branch is seeing the most development. Besides that you will need wsgiutils and python-paste. You make a Paste site with the paste-setup command.

The directory structure

So we use the makesite to build the skeleton application. After this, the following directories are present:

The hello world program

Open up controller/root.py and write the following:

class Controller(SubwayController):
    def index(self):
        return "Hello world"
    index.exposed = True

Then you can start the site with python scripts/run.py. At pointing the web browser at localhost:8080 you should observe a page saying "Hello world".

Using Apache as frontend (the CherryPy "production setup")

The rewrite rule you need is as follows (enable mod_proxy too):

RewriteRule /hello(.*) http://localhost:8080$1 [P]

After this you can access the site through Apache.

Skinning the layout

Subway has concept of skin (a ViewFilter) that can host all the other site content. This is generally a great idea, so we shall make use of it. This changes the Hello program as follows:

# set global variable $siteroot
views['siteroot'] = '/hello'

class Controller(SubwayController):
    _view = views.site

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

This will now look up views/root/site.html and use it as Cheetah template. views has overridden __getattr__. I imagine this design will not prove out to be advantegous in the long run. The $siteroot variable is defined to account for the mod_rewrite setup. To refer to the /public directory you would do $siteroot/public. Within the _view, the content produced by controller is called $content. These pieces suffice for defining a primitive template:

<h1>Hello</h1>
$content

HTML forms

Subway pre- and postprocesses HTML forms. The preprocessing happens once at Subway startup time, and at that time it will analyze the forms for certain tags that live in the form-namespace. A typical expression might be as follows:

<form:iferror name="foo">
Please fill in the 'foo' field.
</form:iferror>
<input type="text" name="foo" form:required="yes">
<input type="submit" value="Send">

Once being aware of the form's properties, Subway is capable of analyzing whether the value for 'foo' is empty or not upon submit, provided the method is wrapped with a decorator. If the above is saved as view/demo/form.html, this would be enough to drive the corresponding form:

@forms.handle(views.form.schema)
def formdemo(self, _errors, foo=''):
    if _errors:
        # form didn't validate
        return views.form(fill_form=True, _errors=_errors)
    else:
        # form did validate
        # maybe do some action now

In particular, after providing fill_form=True you will get your HTML form prefilled from request data for free.

SQLObject

I'm dubious about this piece of programming. This class is too clever by half. I've had modest success in trying to use it, but so far I am not at all sure about committing to using it for real.

SQLObject is limited in ways that make only trivial SQL schemas really supported by SQLObject. For instance, primary key should be only 1 column wide. However there are several perfectly understandable designs that call for multi-column primary keys.

Foreign key referencing columns should/must terminate by _id. Some people even suggest that this should be made automatic. I strongly disagree.