Saturday, March 19, 2011

Bobo and Genshi with Google App Engine


I've wanted to play with Google App Engine for a while now, but I never liked the webapp framework or GAE's rendering engine. Bobo as a framework is simple and pretty intuitive, but doesn't have a rendering engine. Genshi is a XML rendering engine that has lots of great features and allows the programmer to use XML validation on the templates.

Here's how to get Google App Engine to work using Bobo and Genshi.

First, gather your required software. You will need bobo.py, boboserver.py, webop, and genshi along with the Google App Engine SDK. Create a project in your favorite IDE and put everything in the root just like in the screenshot.

Now lets make room for our static files. I put css, images, and js in the static directory. I put my genshi templates in the templates directory. Now let's take a look at app.yaml which tells GAE how to load your application.
application: scottfolio
version: 1
runtime: python
api_version: 1

handlers:
- url: /(.*\.(gif|png|jpg))
static_files: static/images/\1
upload: static/images/(.*\.(gif|png|jpg))

- url: /css
static_dir: static/css

- url: /js
static_dir: static/js

- url: .*
script: main.py
This file is pretty self-explanatory. The handler for images will only match GIFs, PNGs, and JPEGs. Css and js are pointed to sub-directories of static. Everything else runs through main.py. Main.py is very simple and just loads the bobo wsgi application into GAE.
from google.appengine.ext.webapp import util
from bobo import Application

def main():
application = Application(bobo_resources="pagedef")
util.run_wsgi_app(application)

if __name__ == '__main__':
main()
Main.py tells bobo to load the pagedef module (pagedef.py) as its resources. Let's take a look at that file.
import bobo
from lib import render_to_template

@bobo.query('/')
def getHomepage():
context = {'title':'ScottFolio'}
return render_to_template('home.html', context)
You may notice render_to_template which is just a function name I borrowed from Django since many of us are familiar with that shortcut. I am also using the Django-style context pattern and passing it to the rendering function. Let's take a look at that code.
from genshi.template import TemplateLoader
loader = TemplateLoader(['templates'],
auto_reload=True)

def render_to_template(template, context):
tmpl = loader.load(template)
stream = tmpl.generate(**context)
return stream.render()

Again, very simple stuff. The render_to_template function takes in a template file name and context then loads the template and generates a stream using Genshi. It then returns the rendered stream.

For more information on Genshi, please visit http://genshi.edgewall.org/.
For more information on Bobo, please visit http://bobo.digicool.com/.
For more information on Google App Engine, please visit http://code.google.com/appengine/.

Now, back to writing the rest of that web application.