17

As I understand from this database design question, you should use nullable fields sparingly and make a weighed decision each time on whether it would be better to rethink data design instead.

But let's say in some particular case the resolution is to allow a text field to contain an empty value. Say, there's user table and there's short_bio column that is represented by the TextField in Django and is not mandatory. It doesn't make sense to create a separate user_bio table, right?

Now the question is, should the empty value be an empty string or null marker? What are pros and cons for each option? Are there any specifics in how Django works with database that can make difference?


It should be noted that django-lint currently reports on CharField and TextField instances with null=True.

Conversely, ‘storing an empty string for a field left blank is seen as a Bad Idea’ by some developers.

Community
  • 1
  • 1
Anton Strogonoff
  • 32,294
  • 8
  • 53
  • 61

2 Answers2

26

I think that when 'empty string' means 'no value', the empty string should be used in order to avoid mixing nulls and blanks meaning the same thing (e.g. in searching or comparing: in some DBMS you can't compare NULL to NULL directly, you must use the IS NULL operator).

Using the empty string will also make easier to use it 'as is' in reports and other stuffs where the 'short_bio' is used without passing throug the DOM (e.g. using objects.values('short_bio')), without converting Null in ''.

Moreover, Django docs state:

Avoid using null on string-based fields such as CharField and TextField unless you have an excellent reason. If a string-based field has null=True, that means it has two possible values for “no data”: NULL, and the empty string. In most cases, it’s redundant to have two possible values for “no data;” Django convention is to use the empty string, not NULL.

Don
  • 16,928
  • 12
  • 63
  • 101
6

If you need a nullable text field that should be unique but allow multiple NULL values, it may be better to use NULL instead of empty string.

Django always sees NULLs as unique values, meanwhile empty string is always equal to another empty string. See Unique fields that allow nulls in Django and ticket 9039.

To have ‘the best of both worlds’ you can store the empty value as NULL, but display as an empty string via custom form field. A (not tested) example by mightyhal:

from django.db import models


class CharNullField(models.CharField):
    description = "Stores NULL but returns empty string"
    def to_python(self, value):
        # this may be the value right out of the db, or an instance
        if isinstance(value, models.CharField):
            # if an instance, return the instance
            return value
        if value == None:
            # if db has NULL (==None in Python), return empty string
            return ""
        else:
            return value # otherwise, return just the value
    def get_db_prep_value(self, value):
        # catches value right before sending to db
        if value == "":
            # if Django tries to save an empty string, send to db None (NULL)
            return None
        else:
            return value # otherwise, just pass the value
Community
  • 1
  • 1
Anton Strogonoff
  • 32,294
  • 8
  • 53
  • 61