GoogleDroid
GoogleDroid

Reputation: 195

Django: Automatically setting empty strings in model fields to None?

I want to iterate over my model fields within a Django model and check if they are empty string and replace them with a null in the model save() method programmatically. This is because some CharFields need to be unique or have no value.

Example:

class Person(models.Model):
    name = models.CharField(blank=True, unique=True, null=True)
    nick_name = models.CharField(blank=True, unique=True, null=True)
    ...
    age = models.IntegerField()

    def save(self, *args, **kwargs):
        for field in self._meta.fields: # get the model fields
            if field=='':
                field = None
       super(Person, self).save(*args, **kwargs)

The above complains about a creation_counter which is unclear why an attempt to compare those values instead of the field value with the empty string is done.

This could be done manually, but I have too many models....

Any suggestions?

edit: Thanks to everyone who attempted to help me! :D

The solution that seems to work for me is posted by Jazz, but his code isn't showing up in his post. This is my version which is essentially identical, but with an extra check to make sure we are only overriding when necessary:

from django.db.models.Field import CharField as _CharField

class CharField(_CharField):
    def get_db_prep_value(self, value, *args, **kwargs):
        if self.blank == self.null == self.unique == True and value == '':
            value = None

        return super(CharField).get_db_prep_value(value, *args, **kwargs)

Upvotes: 4

Views: 6491

Answers (2)

Shihwei
Shihwei

Reputation: 68

Jazz's answer works like a charm for me.

I just want to point out that if you are using South migration tool, the schemamigration command will fail, unless you specify a introspect rule for the new custom field.

For "simple fields", you can simply add the following code to wherever your field is specified.

from south.modelsinspector import add_introspection_rules
add_introspection_rules([], ["^myapp\.stuff\.fields\.SomeNewField"])

Now the South migration should work.

FYI.

Reference: http://south.aeracode.org/wiki/MyFieldsDontWork

Upvotes: 0

jazz
jazz

Reputation: 2379

In your case, I would suggest a custom model field, which subclasses a CharField and ensures that a empty string is converted to None -- overriding get_db_prep_value should do it.

class EmptyStringToNoneField(models.CharField):
    def get_prep_value(self, value):
        if value == '':
            return None  
        return value

class Person(models.Model):
    name = EmptyStringToNoneField(blank=True, unique=True, null=True)
    nick_name = EmptyStringToNoneField(blank=True, unique=True, null=True)

https://docs.djangoproject.com/en/dev/howto/custom-model-fields/

Upvotes: 11

Related Questions