Mimsy Were the Borogoves

Hacks: Articles about programming in Python, Perl, Swift, BASIC, and whatever else I happen to feel like hacking at.

Django, empty strings, and missing values

Jerry Stratton, September 26, 2007

Django is a great app for handling databases, but there are a couple of places where Django tries hard to be complex for no apparent benefit. One is making it harder to keep track of when records are added and updated. This is basic information that I keep in just about every model in my apps, and the current Django supports it. But the next Django probably won’t, and judging from the discussions on groups.django, the developers currently expect people to override their save methods to do it.

I have a fairly complex set of Django models for Negative Space, and I have never had a need to overwrite the save method. I shouldn’t have to do so for something as basic as remembering when a record was created and modified. I’m dreading the next version of Django; I’ll either have to not install it, or go through every model and override the save method in each one.

The other place where Django is more complex than it needs to be is that it is more difficult than it should be to keep track of when a text field has no data in it. This affects the current Django, and judging from the bug report comments, it isn’t likely to change in future versions.

For example, in the CMS at the office I have a model where records can have filenames and parents. If a record has a filename, that filename must be unique for that parent. Records can also have an off-site URL. They don’t have to have one, but if they do have one, it needs to be unique across the entire database. This is easy enough in MySQL; you just set non-existent values to NULL. Empty strings for non-existent values don’t work here, because an empty string is a real value. If the column is set as unique, it can’t have more than one empty string.

It looks like it‘s easy in Django, too: just set blank=True, null=True, and unique=True (or apply unique_together in the model’s Meta class). Django, however, does not assume that the combination of null=True, blank=True, and uniqueness in a CharField means that we need a NULL there instead of an empty string. The result is evil-looking errors when you try to insert multiple records with unknown values in unique fields.

The recommended way to fix this is to override your save method. I’ve never seen an example from the people who say that, though, so I’m going to give an example here. In this case, it really is simple, once you know two important pieces of information: that Django treats Python‘s “None” as NULL, and that you need to use the “Super” function to pass program execution up to the parent class.

[toggle code]

  • def save(self):
    • #these fields are marked as null=True, empty values mean the absence of a value:
    • if self.offSiteURL=="":
      • self.offSiteURL = None
    • if self.filename=="":
      • self.filename = None
    • super(Page, self).save()

For this to work, you still have to specify null=True in the field definition; this ensures that Django tells your database software to allow NULLs in that column.

  1. <- FileMaker to Django
  2. Selected iTunes Playlist ->