I got back from a concert last night with a significant part of my bloodstream still consisting of Red Bull, so I sat down to do my first substantive update to my blog software in about six months. I switched to date-based URLs, switched blog post pages to a 2-column layout, and added monthly archives.

I wish this were also a "I promise to start blogging regularly again" post, but I've said that enough times that I know better. I do plan to put aside some time for writing during PyCon, but I make no promises.

OK, so I think I owe you some actual content. I'm going to go over a few details of each change's implementation and rationale.

Date-Based URLs

Changeset in question: 5a586a8c2f8f

I had this on my to-do list since seeing Malcom Tredinnick's Canonical Date Redirect article. I originally went with slug-only URLs because, when I originally wrote the engine, I thought date-based URLs were ugly - probably because I saw it too often on Wordpress blogs and the like.

I don't know what I was thinking. I certainly didn't know what I was doing. But hey, what's new?

URLs can contain a lot of useful metadata. A slug is the most obvious bit of information, to give the user an idea of content they can expect at the URL. Dates are also useful, by letting the user know whether the content is current or out-of-date.

Unlike Malcom, I didn't implement URL patterns and views for each level of the date breakdown - year, month, day. I might do that at some point, but didn't have enough time to do it last night before I sensibly went to sleep.

Sshh, Don't Tell Anyone, But...

Although the URL is now generated with date fragments, the view doesn't actually pay attention to the date fragments; my slugs are still unique, so that's the only part that is used to retrieve the object. So you can change the date in the URL, and it'll still retrieve the entry successfully, as long as it matches the URL pattern regex.

The culprit, as usual, is my laziness. Going from 'jan' to 1, 'feb' to 2, and so on isn't particularly difficult - Django does it in django.views.generic.date_based.archive_month, if you'd like to see how it's done - but it does involve a bit an ugly bit of datetime manipulation, and I'd just as soon let that code stay in Django and out of my own codebase.

The GUID Situation

One thing I wanted to avoid was spamming everyone's feed reader. My feed item GUIDs are based on the post URLs, based on the assumption that my URLs wouldn't change. But seeing as my URLs did just change, I had to find a way to keep the old URLs working and provide a seamless transition to the new URLs in newly-generated GUIDs, while not changing any existing GUIDs.

One way to do this would have been to add a guid field to my Entry model, but that seemed like a violation of DRY - if I can generate the GUID consistently from the Entry fields, then I should. However, there's no way to avoid adding some state. It would also have been possible to use date-based GUID generation - posts before 2009 would use the old format, while 2009 and later would use the new format. But having that in my code felt ugly - and it was still adding state, just as a weird bit of code instead of a field on the model. Given the choice, I'd much rather keep my state in my data, and not in my code.

So instead, I added a .feed_url_scheme field, which seemed like the smallest and most explicit amount of state I could add to the model. I created the new column in the database manually and set all existing posts to use the slug-only scheme, but set the date-based scheme as the default for new entries.

All told, it was a nice little exercise in incremental improvement.

2-Column Layout

Changeset in question: 41bb13fc4f7d

I added the 960 Grid System to my site a while ago in anticipation of something other than my single-column layout, but this is the first time I've made use of it. I have to say, 960 is the first CSS framework I've really been able to happily use - its limited scope is a huge plus.

The 2-column layout narrows both the entry text itself and the comments, which are now in the right column. My text was too wide anyway - this puts it at about 50-55 characters per line, which, if anything, is too narrow. I might bump down the font size a little to compensate.

I'm starting to tire of the minimalistic feel of my current style, but I'm not changing anything else about it for now. It'll probably be a few months before I get to that.

Monthly Archives

Changeset in question: b16f4fab397a

I went all-out OOPy for this one. It's nothing a few nested dictionaries couldn't have handled, but I'm still in a phase where I don't mind writing 80 lines of support classes to save 20 lines of view code, which is pretty much what I did. The advantage, I think, is that the view code is dead-simple, and the Archive object is potentially reusable if I remove the hard-coding of the .pub_date attribute - which I don't plan to do until I actually find a use case to reuse it.

PyCon 2009

The economy is going through a bit of a phase, but if you're able to make it to Chicago for PyCon, catch me sometime and say hi. I had a blast last year - I'm sure it'll be awesome again this year.