farblog

by Malcolm Rowe

Hosting Jam

Jam is cool.
Tiny Surprise, by Sebastian Mary (used under CC BY-NC-ND 2.0)

When we first started running our London Open Source Jam meetups, we took over part of the public Google Open Source Program Office wiki, and asked people to sign up by filling out their details on a wiki page.

That worked well for a bit, but the publicly-visible email addresses were a bit of a pain (unless you really wanted phone calls from recruitment agencies), and you had to create a wiki account before you could sign up. So Joe Walnes threw together a PHP/MySQL-based signup page at osjam.truemesh.com that we’ve used for the last six months or so.

That’s worked well for people signing up, but it’s been a bit annoying for us: because it runs on Joe’s home machine, the only administrator is Joe, the way to edit the signup list is via the mysql command line, and the way to edit the text on the page is to edit the PHP script.

You can see where this is going, I’m sure. Tuesday’s release of the Google App Engine gave me an excuse to look at how hard it’d be to port Joe’s PHP to a hosted Python application.

How hard? About six hours. If that seems like a long time, bear in mind that it included not only learning about the App Engine, from scratch (I’d been aware of the project internally, but I hadn’t tried anything out until Tuesday evening), but also finding out how to do trivial stuff in Python (“How do I make a date from a string, anyway?”) and adding a bunch of features to the original port. Here’s the new site: osjam.appspot.com, same as the old site.

Since there’s a not a lot to see at the moment (we’ve not yet announced the next event), you can also download the source and play around with a local copy, which isn’t a bad way to see how the App Engine works. Alternatively, I’ve put the source online in a browsable format, if running software’s not your thing. Don’t expect the code to be a perfect example of either the App Engine or Python: it’s something I hacked up quickly to solve a problem.

One note: you might need to install Python 2.5 to run the App Engine SDK tools. Although they allow you to run with Python 2.4, they print up a scary warning at startup, and also depend upon some modules that weren’t part of the core distribution until 2.5. Someone with better Python skills than I — not hard! — could probably just install the right modules, but I’m lazy, so I just downloaded the Python 2.5.2 tarball, and after a quick ./configure --prefix=~/usr; make; make altinstall, had a ~/usr/bin/python2.5 that I could run the App Engine scripts with, without touching my system Python installation.

To run everything locally, download the osjam source and Google App Engine SDK tarballs and expand them into the same directory (you should be left with a directory called google_appengine/ and one called osjam/). Note that you don’t need to sign up for an App Engine account to run things locally, if you don’t want to.

Then, run the development application server:

$ python2.5 google_appengine/dev_appserver.py osjam/
INFO     2008-04-10 09:36:43,814 appcfg.py] Checking for updates to the SDK.
INFO     2008-04-10 09:36:44,257 appcfg.py] The SDK is up to date.
WARNING  2008-04-10 09:36:44,257 datastore_file_stub.py] Could not read
datastore data from /tmp/dev_appserver.datastore
WARNING  2008-04-10 09:36:44,258 datastore_file_stub.py] Could not read
datastore data from /tmp/dev_appserver.datastore.history
INFO     2008-04-10 09:36:44,262 dev_appserver_main.py] Running application
osjam on port 8080: http://localhost:8080

Cool! Let’s go to http://localhost:8080:

Oops! No active event!

Ah. Everything’s working, but there’s no data. We’ll need to create an event before anything useful happens. Fortunately, there’s a hokey admin page at http://localhost:8080/admin. Note that this URL is protected by the login: admin statement in an application configuration file called app.yaml, so you’ll be prompted to “sign in” before you can access the page — though since this is running on a local development server, you can sign in as anyone. Make sure to check the ‘Sign in as Administrator’ checkbox, though.

Once you’ve signed in, you’ll see an empty table with an inviting ‘New event’ link. Select it, then enter some details about your event (including some number next to the ‘How many places?’ label), check the ‘Make this event the active one’ checkbox, and click ‘Create Event’. Now go back to the home page, and you’ll be able to sign up for your event. Woohoo!

As well as the app.yaml file, which mostly configures the URL ↦ handler mappings for the application, it’s worth taking a look at model.py, which defines the models used in the datastore, main.py, which defines the code for the root (GET) and /signup (POST) handlers, and main.html, which is the Django template for the main page. It’s worth mentioning that you’re not limited to Django’s templates: it’s just that the SDK includes that engine by default. If you want to use something else (or if you want to use the rest of the Django framework), you just include it in your application (much as I did to make use of the python-markdown2 module).

Another cool thing to play around with is the built-in console at http://localhost:8080/_ah/admin (only available when running on the development server; hosted applications get a full-featured dashboard on appengine.google.com). It’s also worth going through the SDK’s Getting Started guide, which covers everything in a lot more depth.

When you’re looking around at the documentation, you may notice some rough edges (it is a preview release of the SDK, after all). For example, a bulk upload article — which appeared yesterday, just as I was wondering how to do bulk uploads! — makes reference to SearchableEntity objects, which aren’t documented anywhere, making it a little hard to figure out what’s going on. Fortunately, the Python is pretty well documented, and in this case the SDK’s google/appengine/ext/bulkload/__init__.py contains a lot of useful comments, so I was able to create a bulk upload handler of my own and import all the data from the old MySQL database.