The Global Django

One thing that annoys me in many US-based software projects is the narrow mindness of the developers who seem to forget that there is life outside of the US, too. Django has been a very international project from the day one, with admin interface translated to 43 languages and the contrib.localflafor full of great localized stuff like validators for Finnish social security number etc.

After Adrian’s official announcement of the worldwide Django sprint (that will be held on Friday, Sept. 14, 2007) there has been a steady flow of volunteers adding their names on the wiki page. As I write this, over hundred volunteers from 26 countries have signed up for the event. It’s just amazing.

I wish more open source projects would have as great community that Django has. And greetings to everyone who is attending the sprint next Friday — let’s have fun! 🙂

Using Jaiku API with Python

I’ve slowly fallen in love with Jaiku. It’s a microblogging platform much like Twitter, but with fun features like ability to add feeds from other services (like Flickr, Ma.gnolia.com, Last.fm or any arbitrary source) to your stream and a nifty client for Series 60 phones. Jaiku also has an open API for easy hacking. I was amazed how easy it was to use.

My goal was to get my current presence data and location from Jaiku. After 30 minutes of coding (of which I watched the Simpsons about 20 minutes) I had the following 25 lines of code in my jaiku.py:

 from django.utils import simplejson  from urllib import urlopen from time import strptime from datetime import datetime, timedelta  JAIKU_USERNAME = 'uninen'  def get_jaiku_presence():     """Returns user Jaiku presence as dict or False if errors."""      url = 'http://%s.jaiku.com/presence/last/json' % JAIKU_USERNAME      try:         result = simplejson.load(urlopen(url))          # pythonize needed fields         time = strptime(result['created_at'], "%Y-%m-%dT%H:%M:%S GMT")         result['created_at'] = datetime(*time[:5]) + timedelta(hours=3)         result['comments'] = len(result['comments']) or False          return result      except IOError:         return False

It’s very simple and dead easy to use:

In [1]: from unessanet.misc.jaiku import get_jaiku_presence  In [2]: get_jaiku_presence() Out[2]:  {u'comments': False,  u'content': u'Savitehtaankatu, Turku, Finland',  u'created_at': datetime.datetime(2007, 8, 17, 0, 20),  u'created_at_relative': u'3 hours, 8 minutes ago',  u'icon': u'',  u'id': u'9552365',  u'location': u'Savitehtaankatu, Turku, Finland',  u'title': u'Enjoying the rain',  u'url': u'http://Uninen.jaiku.com/presence/9552365',  u'user': {u'avatar': u'http://jaiku.com/image/13/avatar_32113_t.jpg',            u'first_name': u'Ville',            u'last_name': u'S\xe4\xe4vuori',            u'nick': u'Uninen',            u'url': u'http://Uninen.jaiku.com'}}

Feel free to modify this to your needs.

Next up is a system for storing these presences to a local database and drawing a location trail to Google Maps or something similar…

PS. My Jaiku stream is at uninen.jaiku.com 🙂

It Could Be Worse

After a long-awaited summer vacation (including an unforgettable visit to Norway) I’m back to sitting indoors during these amazingly beautiful summer days.

This monday felt truly a monday until I saw this blogpost revealing the code for Facebook home page. Man, that gives one perspective. It’s been only about eighteen months since I dropped PHP for Python. The switch has been almost as fulfilling as the switch to my first Mac back in the day. Seeing that ugly and messy PHP code just made me smile; at least I don’t have to put up with anything like that anymore!

This is not to bash PHP or PCs (although they both suck) but to remind me that it’s really great to be able to work on interesting projects with Python and Django. It could be much worse. I just forget it much too often.

Lightning talk: Hacking EuroPython.org (with Django)

I gave a lightning talk yesterday at the EuroPython conference about my little MyEuroPython mashup. The intention of the talk was not to promote the site but to raise a conversation about how to make better conference websites (and especially EuroPython.org).

Main points of my presentation were that conferences are about communication and interaction. Current EuroPython.org does not give any tools for that, and it would be great to have something more 2.0 for the site.

For example:

  • Simple site structure with good (live)search
  • Registration and personal preferences using OpenID
  • Allow commenting of sessios
  • Provide a personalizable timetable (that is useful for example when using a mobile phone)
  • Free the data; RSS feeds (and possibly other APIs?)from everything
  • Aggregate blog entries, images, links to the main site

Good thing was, there was talk about the presentation afterwards, and we actually volunteered for doing the EuroPython.org with Django next year. Hopefully the discussion lives on!

At EuroPython 2007

I arrived at Vilnius Lithuania with my colleague on saturday. We spent the weekend by exploring the beautiful old city and today we’re getting into the business with EuroPython.

Only a couple of weeks late, I today published MyEuroPython, which provides an alternative to the EuroPython conference schedule (powered by Django — of course). It’s very untested and unpolished at the moment, but at least I’m using it myself 🙂 I’m giving a lightning talk about the site later on today.

Hopefully we’ll get a some kind of Django-meetup arranged this week. I’ll be posting more on the conferense soon. Meanwhile, my Jaiku page updates somewhat often and Flickr images, too.

Django: Say Hello to Unicode

After weeks of testing, the Django unicode-branch was merged into trunk today. This changeset brings huge improvements to unicode-awareness of Django and it also fixes a lot of unicode-related bugs. From the announcement at django-users list:

This should be backwards-compatible for all practical purposes (providing you only use ASCII data). The only real difference you will notice in that case is that model fields are Unicode strings instead of bytestrings in type, but since they are ASCII data anyway, that shouldn’t make any real difference.

See Unicode data in Django and Porting Applications (The Quick Checklist) for more.

Furthermore, there was also another great commit today fixing a bug that has always been in top five of my personal “The things I hate most about Django”-list. Changeset 5608 adds finally “unicode-aware slugify filter (in Python) and better non-ASCII handling for the Javascript slug creator in admin”. Until today, slugify-function converted a typical non-english title like “Tässä on älyttömästi ääkkösiä” into (totally unreadable) “tss-on-lyttmsti-kksi” which of course sucks big time when every other slugify function on the planet makes it something like “tassa-on-alyttomasti-aakkosia” (which is totally readable).

I’m really, really happy that Django is slowly but firmly maturing into a unicode-friendly framework. Kudos for Malcolm Tredinnick for his huge efforts on the unicode-branch and also big thanks to everyone who helped with testing and bugfixes!

iPhone for Nerds

Remember my rant from January about how Nokia sucks? I was basically really upset about the fact that Apple could enter the phone business with something as cool as iPhone when Nokia and others have been making these really crappy phones for decades. Well, couple a weeks ago I got a new phone; Nokia N95.

Two Alike

There are not so many real competitors for the iPhone. By real competitor I mean a phone that could be seriously thought as an “iPod-killer”, a multimedia (video, imaging) device and a smartphone with good networking capabilities. Nokia N95 is definitely one of those few devices. While it doesn’t have a pretty UI like the iPhone, it does, however, pack an impressive feature set that outperforms iPhone in many areas.

Much of the criticism against the iPhone is about its price. Compared to N95, iPhone seems almost cheap. Well, almost. The less expensive iPhone is yours for $500 bucks. The high-end model sets you back $600. And Nokia N95? It’s around \$750. That’s sevenhundredandfifty dollars — for a phone. So please, iPhone is not the only expensive phone on the market.

(For the record, I’m not that rich. In Finland you can get a N95 with a two year contract for zero euros. I love contracts 🙂

In addition to rich feature set and high price point, these phones do have at least a one more thing in common: their battery life is ridiculously low. Of course, no one knows exactly how long the battery will last on the iPhone, but it is obvious that during intensive use it’s not going to be days but hours. And when it’s not days, it pretty much means that you must charge it every single day. Which sucks big time.

Nokia N95 In A Nutshell

  • 2.6″ screen (320×240)
  • 160 Mb onboard memory, support for up to 4 Gb microSD card
  • Dedicated keys for controlling media playback
  • Really Good 5 Mpix camera
  • Wlan, 3G (UMTS)
  • Built in GPS (with Nokia Maps)
  • Runs on Series 60 3rd Edition FeaturePack 1

For a nerd, the most significant differences to iPhone (other than the UI, of course) are N95s better connectivity features, built in GPS and the fact that Series 60 platform is absolutely great for hacking. (And there are lots of free and open source software available. Real software.)

By the way, the Safari browser on iPhone is using the same open source Webkit-engine that is powering Series 60 browser too.

Mobile Hacking

Apple issued a press release earlier this month stating that “evolutionary iPhoneâ„¢ will run applications created with Web 2.0 Internet standards”. Yippee! So, for iPhone you can build shitt.. err. shiny interfaces on web applications and link phone numbers from them. (Want to know a Big Secret? href="tel:+5551234"). Man, that’s so cool! Or at least it was back in 2000.

I really don’t know which puts me off more; Nokia and others making really bad UIs and half-baked software on top of a decent operating system, or Apple making uber cool “runs on OS X” iPhone and crippling it with no SDK.

Series 60 phones have their downsides, but for developers the platform is wide open. In addition of dozens of open source programs that you can learn from, there are things like Python for Series 60 that lower the barrier for mobile development significantly. Furthermore, projects like Apache 2 port for Series 60 have opened amazing possibilities of which almost none have been explored yet.

Nokia alone has many other cool open source projects running and there are lots of people working on all sorts of cool hacks. (For example the RaccoonOnMap, which is a Mobile Web Server and Google Maps mashup that puts your phone on a map).

Getting a developer certificate for Series 60 3rd edition is, albeit free, a bit pain in the butt. But now that I have one (after few hours of installing stupid win-only software on Virtual PC and fighting trough the registration process), I’ll definitely try some Python hacking on my N95. I still think it’s a shame that you cannot do anything like this on an iPhone. Sure, it’s a smartphone “for the rest of us”, but if it really runs OS X, why not open it up for developers?

Until that happens, I guess the N95 is the iPhone for nerds.

Using Capistrano to Deploy Django Apps

Capistrano is a great tool for automating tasks on one or more remote servers. It’s mainly used for deploying Rails apps but it can fairly easily be used for other tasks, too. After reading the new getting started docs for upcoming 2.0 version, I created a simple script for deploying Django apps with Capistrano.

Feeling Lazy

Let’s be honest. Deploying Django apps is dead easy. There really isn’t much stuff that would need automation. But there are many situations where you are doing much more work on the remote server than you’d really want to. The more commands you execute the more the chances of screwing up increases. And personally, I’m just too lazy for doing simple monkeywork on the command line again and again. This is where Capistrano comes along: it can do most of the work for you.

Do it Capistrano Way

Capistrano, like Rails, assumes many things about your project. For example, it assumes that you want to deploy a Rails app, and that you are using subversion for version control. Also the current documentation is mostly written from Rails viewpoint. Fortunately the docs have been improved lately and Capistrano is starting to present itself as a true multipurpose tool — which it really is.

I generally like the Rails-way of doing things. When things are always done in a consistent way, developing becomes really easy. (Don’t underestimate the weight of cognitive load!) Until you want to be different. At that point everything usually falls apart. Fortunately Capistrano is fairly flexible in this regard — you can do things your own way.

Capistrano has built-in functions for doing stuff like deploying (a Rails app), controlling FCGI servers, and simple rollbacks. I wanted to do something very basic and in a way that could be easily modified and expanded. After learning the basics and reading Capistano chapter on Rails manual, I wrote and tested the following script in just few hours. It uses just basic shell commands, none of those fancy Capistrano functions. I think that this script is a good starting point for building smarter and more complete scripts.

Run Me Baby One More Time

Okay, let’s cut the crap. In brief, what I wanted to do with Capistrano was ease the upgrading of production sites by automating a set of things I do when upgrading a production site.

I work for a small company where we run dozens of Django sites on many different servers. (I believe we are if not the only one, at least one of the few companies in Finland that specialize in Django.) A typical project consists of one subversion repo and a server setup of Apache+mod_python and dedicated servers for database and static files. All of our projects are configured for easy off-line development and most of them usually need some tweaking on the production server after a subversion checkout.

Personally I like to do development with real data, so normally just before deployment I import the live database to my local machine, modify it if needed, and finally upload the modified dump back to the production server. Naturally, this only works on small sites, but for those (and for me) it works great.

So, my first Capistrano script automates what I normally do manually for an upgrade of a small site. The steps are:

  1. Log in to a remote server
  2. Run svn update in project directory
  3. If there are changes in models:
    1. Backup old database
    2. Upload new database to server
    3. Import new database
    4. Delete the just loaded sql-file
  4. Move settings.py in place
  5. Reload apache

Most importantly, Capistrano does all this in a way that in a case of “OMG! OMG!11 I JUST BROKE THE ENTIRE SITE!11” (which of course never happens because I’m perfect and I never do mistakes) I can roll back all of the changes in a matter of seconds.

The Capistrano script that does all the above looks like this.

This script can be run from the local development machine. I put mine in the projects root directory. And when upgrading the site, I run the upgrade_project-task that I wrote by typing cap upgrade_project. Capistrano then asks for my password, logs in to the remote server(s) and executes every command defined in given task, outputting the results on the terminal as it goes. It’s finished before you can say “freaking cool”. For added security you can (and should) use SSH keys for authentication, and Capistrano lets you even define a gateway server for piped connections.

The capfile is a ruby script that defines one of more tasks. A task consists of one or more commands that will be executed on one or more remote servers. (Capistrano can run a task simultaneously on several remote servers.) A small task could be something like running ls on a remote server, while a complex one could do everything needed for deploying an application on a virgin box. There really isn’t much limits to what Capistrano can do.

IM IN UR DJANGO

Above example is a quick & dirty proof-of-concept type of script. I know it can be bettered quite a bit. It would be nice to see more Django-related scripts out there. If you have used Capistrano for Django-related work, share your experiences! Also bettering the Capistrano documentation wouldn’t hurt. Django wiki is one good place for sharing.

For something to think about, with a little bit of extra work it would be possible to do totally virgin deployment with configuring apache and media servers, too. I’m also pretty sure that it would be possible to use some of the Capistranos built-in helpers for deploying non-Rails apps. Google for using Capistrano for more info.

I hope this post got you at least a bit interested in Capistrano. If you have any suggestions or comments, please add them below 🙂

Django unicode-branch: testers wanted

The long-waited unicode-branch is finally at a stage that wider community testing is needed. Read the notification at django-users mailing list.

Malcolm has done terriffic job with the branch and there are already fairly solid documentation available. For most people, the short checklist (five steps, maximum!) is all you need to convert your applications to handle unicode well. If you want more information, check the detailed documentation from the trunk.

Using this branch means an end for the numerous unicode-related problems (for most of them, anyway) when using Django. So, this is a must for every djangonaut who is living in the Real World 😉

Go on, get on with it! 🙂

Released: Star Rating Script for YUI

I just released a first version of my Star Rating Script for YUI. It’s a pretty straightforward script that uses some ajaxy woodoo for rating stuff. And, of course, it’s fully degradable so if JavaScript isn’t available, it works like a regular form.

I’m planning to extend this a little bit in near future to use it with a general Django templatetag, much like contrib.comments. That way you could add ratings to any Django object as easy as adding one templatetag to your template. At the moment this is only on planning stage, so I wouldn’t hold my breath for it just yet 🙂