[Fixed]-Nullable TextField or empty string in Django model?

27👍

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

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

Leave a comment