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 at 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
- Converting an existing Django model to Django-MPTT
- Using a SQL database to mimic a filesystem will, eventually, create bottlenecks when it comes to traversing the filesystem. One solution is modified preordered tree traversal, which saves the tree structure in an easily-used manner inside the model.
- Two search bookmarklets for Django
- Bookmarklets—JavaScript code in a bookmark—can make working with big Django databases much easier.
- Fixing Django’s feed generator without hacking Django
- It looks like it’s going to be a while before the RSS feed generator in Django is going to get fixed, so I looked into subclassing as a way of getting a working guid in my Django RSS feeds.
- ModelForms and FormViews
- This is just a notice because when I did a search, nothing came up. Don’t use ModelForm with FormView, use UpdateView instead.
- Django: fix_ampersands and abbreviations
- The fix_ampersands filter will miss some cases where ampersands need to be replaced.
- 29 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