[Twisted-web] Including templates in CGI

Cliff Wells clifford.wells at comcast.net
Sat Jun 11 02:37:28 MDT 2005


I just started playing with Nevow yesterday, and I've got a question.  

I've been using PHP/Smarty for doing websites because it's pretty easy
and I've been unhappy with most of the Python web frameworks I've seen
(most of them have pretty ugly template syntax or are overcomplicated).
However, PHP is um, not so good, so I thought I'd make the leap to Nevow
which seems to satisfy my need for simplicity and not-ugliness ;)

Anyway, my typical design pattern for a site is to have an index.html
template with the main layout, and then include another template
depending on a GET/POST variable (e.g. http://example.com?page=home).
In PHP/Smarty, there is an "include" directive that will directly inject
a second template:

  { include file="$page.html" }

I haven't found an equivalent in Nevow, but I hacked this together (note
that I am using Apache/CGI, not Twisted:

def template(filename):
    Prepend the full path to the template directory
    return "/var/www/virtual/example.com/public_html/templates/" + filename

class Index(rend.Page):
    Looks first at the "file" attribute for the fragment to include, if that isn't provided
    looks at the "variable" attribute for the name of the get/post variable that contains the
    name of the fragment to include.  Failing that, just use a default fragment.
    defaultPage = 'home'
    docFactory = loaders.xmlfile(template("index.html"))

    def render_include(self, ctx, data):
        filename = ctx.tag.attributes.get('file')
        if filename is None:
            filename = ctx.arg(ctx.tag.attributes.get('variable'))
        if filename is None:
            filename = self.defaultPage
        filename = template(filename + '.html')

        if os.path.exists(filename):
            fragClass = rend.Fragment
            fragClass.docFactory = loaders.xmlfile(filename, ignoreDocType=True)
            ctx.tag.fillSlots(ctx.tag.attributes.get('slot'), fragClass())
            return ctx.tag
            return "Page not found."

<div id="content">
  <nevow:invisible nevow:render="include" variable="page" slot="content">
    <nevow:slot name="content" />

This allows me to either specify the included file by accessing a GET/POST variable:

<nevow:invisible nevow:render="include" variable="page" slot="content">

or directly specify the template like:

<nevow:invisible nevow:render="include" file="home" slot="content">

This all seems to work just fine.  However, now I'm curious if there is a better/more direct way of achieving this.

Cliff Wells <clifford.wells at comcast.net>

More information about the Twisted-web mailing list