This post has been a long time in the making. A year ago, I started work on my Twanguages code. This was code to analyse a corpus of Twitter messages, and try to discern patterns about language use, geography, and character encoding. I decided to use the Django web framework and the Python language for the Twanguages analysis code. I know Python, but I was learning Django for the first time.
Django is really, really marvellous. When I tried this expression, and got the Python array of records I was expecting,
q2 = TwUser.objects.annotate(ntweets=Count('twstatus')).filter(ntweets__gt=1)
I wrote in my log, “I think I just fell in love. Power and concision in a tool, awesome.”
But Django gave me fits. It has its share of quirks to trap the unwary novice. Eventually I began writing notes about “Django gotchas” in my log. Some of them are Django being difficult, or inadequate. Some are me being a clueless novice, and Django not rescuing me from my folly. But all of them were obstacles. I share them in the hopes of helping another Django novice.
Here are my Django gotchas. They are ranked from the most distressing to most benign. They apply to Django 1.1, the current version at the time. (As of August 2010, the current version is 1.2.1.) A couple of gotchas were addressed by Django 1.2, so I moved them down to a section of their own. The rest presumably still apply to Django 1.2, but I haven’t gone back to check.
S2 = models.TwStatus.objects.get( key )
I got a lot of weird errors, e.g. “ValueError: too many values to unpack” (where key is string) and “TypeError: ‘long’ object is not iterable” (where key is long). I had made a mistake, of course; the call to get() should have a keyword argument of “id__exact” or the like, not a positional argument. The correct spelling is this:
S2 = models.TwStatus.objects.get( id__exact=key )
The gotcha is that Django’s .get() isn’t written defensively. It isn’t very robust to programmer errors. Instead of checking parameters and giving clear error messages, it lets bad parameters through, only to have them fail obscurely deep in the framework. If defensive programming of the Django API would slow it down too much in production, I’d love to have a debug mode I could invoke during development. Continue Reading »