This blog is now hosted at

Monday, March 15, 2010

A tale of two registrations

It was the best of registrations, it was the worst of registrations... just kidding.

Here are two alternates for the new Sage Steps registration page, and I'd like to solicit your feedback.

Which of these do you like better? The mad-libs version, or the "traditional" version? Read more...

Saturday, March 13, 2010

I'm psychic!

I have developed a tremendous psychic ability to read people's minds.  This has taken years of training, and arduous study at a Shaolin temple, but I'm finally ready to "out myself".

So here it is.

I'm going to read your mind.

Here's the question, and then I'm going to tell you what you were thinking:

How many kilowatt hours did you use last month?

And the answer?

I'm getting something... vaguely... one of your relatives is trying to communicate from beyond the veil...

Here's what you're thinking: "I don't know."

Aren't I amazing?  Well, yes, but that has nothing to do with it: I've asked this question a lot of times.  I have had one person that knew (and he's in a "carbon measurement" startup).  The rest answered, "I don't know."

It is very difficult to improve something that you measure, and things that you measure improve virtually automatically.  It is time to begin to measure how much energy, water and fuel that you use.  Because we can all improve our environmental impact.

Note that this doesn't address any particular ideology: you should be measuring whether you want to save the planet, or if you want to save money every month on your power bill. Read more...

Thursday, March 11, 2010

Design prototype for Sage Steps

This is something that I've been working on for a bit, and I'd really appreciate your feedback. Read more...

Thursday, March 4, 2010

Django: Generators are your friend

Pro tip: if you need to shove a lot of data through a Django view, DO NOT attempt to create a big string-- use a generator.

Here's something that seems sensible on the surface:

body = ""
for region in regions:

  for zip in region.zipcode.iterator():
    body = body + "\t".join(
           [region.region, zip.zipcode]
           ) + "\n"

resp = HttpResponse(body, mimetype='application/ms-excel')
resp['Content-Disposition'] = 'attachment; filename=%s.xls' % (unicode("Regions"),)

Except when the set of regions and zipcodes gets large!  Let's consider the following replacement that uses a generator:

def dump_it():
    for region in regions:
       for zipcode in region.zipcode.iterator():
           yield "\t".join(
              [region.region, zipcode.zipcode]
           ) + "\n"
resp = HttpResponse(dump_it(), mimetype='application/ms-excel')
resp['Content-Disposition'] = 'attachment; filename=%s.xls' % (unicode("Regions"),)

There is a slight performance difference; the latter takes a few seconds (2 seconds for almost 70K resulting rows on my dog of a laptop).  However, I attempted to benchmark the former on the same dataset, and it took almost 13 MINUTES (775 seconds).  So, slight, meaning within 3 orders of magnitude.

Monday, March 1, 2010

Django Forms: Alternate Date Handling

For usability on the "score" page at Sage Steps (free registration required if you want to check it out), we decided that the best method to present a date was a simple drop-down with, e.g. "February 2010" as the text.

I tried out several permutations with mixed luck, but then happened upon the following recipe:

def month_year():
    today =
    today = date(today.year, today.month, 1)
    dates = []
    for i in range(1,13):
        if (today.month > i):
            month = today.month - i
            year = today.year
            month = 12-(i-today.month)
            year = today.year - 1
        mon = date(year, month, 1)
        dates.append((mon, mon.strftime("%B %Y")))
    return dates

This creates a set of tuples, e.g.: (date(2009,3,1), 'March 2009'),

month = DateField(widget=Select(choices=month_year()))

This will produce the drop-down as above, and


Will actually return a object (trust me, that's a good thing). Read more...