3
votes

The Django docs say:

Avoid using null on string-based fields such as CharField and TextField because empty string values will always be stored as empty strings, not as NULL.

So I set up my model like

class Address(models.Model):
    address_num = models.TextField()
    street_predir = models.CharField(max_length=2, default='')    # optional
    street_name = models.TextField()
    street_suffix = models.CharField(max_length=4, default='')    # optional
    street_postdir = models.CharField(max_length=2, default='')   # optional

and then create an object that's missing the optional fields

raw_address = '1234 MAIN ST'
# Run this through an address parser - this returns a dictionary of address components
# Optional fields are returned as None if not present
components = parser.parse(raw_address)
address = Address(**components)
address.save()

But I'm getting the error

null value in column "street_predir" violates not-null constraint
DETAIL:  Failing row contains (8633570, 2057 ANCHOR ST, 2057, null, ANCHOR, ST, null, null, null, ANCHOR ST, null, null, )

Can anyone explain why this isn't defaulting to an empty string? FWIW I'm using Django 1.7.4 and a Postgres DB.

2
No need for default='', you should rather use blank=True to allow empty values in forms. Can you post the traceback and possibly the contents of from django.db import connection; print(connection.queries)? - knbk
Can you also post the code that creates the object, or any custom save methods? Somewhere, you're explicitly setting None instead of an empty string. - knbk
The "... will always be stored as empty strings, not as NULL" part does not seem to hold anymore: code.djangoproject.com/ticket/4136#comment:42 - djvg

2 Answers

3
votes
# Run this through an address parser - this returns a dictionary of address components
# Optional fields are returned as None if not present
components = parser.parse(raw_address)

This explicitly sets the value to None, which is directly translated to NULL in the database. You should remove all keys which have value None or replace the value with '' instead:

components = {k: v for k, v in components.items() if v is not None}

This will only set the non-empty components, and the others will default to an empty string instead of NULL.

0
votes

In the quoted text you pasted, a bit after it states:

you will also need to set blank=True if you wish to permit empty values in forms, as the null parameter only affects database storage (see blank).

For strings you should use blank=True

class MyModel(models.Model):
    required_string = models.CharField()
    optional_string = models.CharField(blank=True, default="")