Django, empty strings, and missing values
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.
- NULL (Wikipedia)
- “Since Null is not a member of any data domain, it is not considered a ‘value’, but rather a marker (or placeholder) indicating the absence of value. Because of this, comparisons with Null can never result in either True or False, but always in a third logical result, Unknown.”
- NULL fields and Unique keys
- “We are not going to interpret empty strings as NULL. They are not the same thing, in general. I think this is something that needs to be taken care of in the model's save() method or as the data is cleaned (converted from form to Python objects).”
More Django
- Django: fix_ampersands and abbreviations
- The fix_ampersands filter will miss some cases where ampersands need to be replaced.
- Custom managers for Django ForeignKeys
- I’ve got one really annoying model for keywords. There’s one category of keywords that, by default, should not show up when used as a ForeignKey for most models. Key word: most.
- Fixing Django 1.2.4’s SuspiciousOperation on filtering
- When you get the message “Filtering by keyword not allowed” in Django 1.2.4, here’s one way to fix it.
- Reusing Django’s filter_horizontal
- Just as with pop-ups, it’s possible to use the built-in JavaScript for filtering multiple-selection popups on custom forms.
- Django formsets and date/time fields
- Date/Time fields in Django formsets appear to have incompatible default values, resulting in forms using them always looking as though they’ve got a new entry when they don’t.
- 25 more pages with the topic Django, and other related pages

I know this is quite old, but I just ran into this issue and it provided a good overview. Thanks!
I solved the dilemma by adding "default=None" for the fields that have to be unique IF provided - works fine so far and seems to be the shortcut to your solution.
openinformation at 10:23 a.m. August 5th, 2011
az21X