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)
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/
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
精彩评论