from django.core.exceptions import ImproperlyConfigured from django.db import models class NullCharField(models.CharField): """ CharField that stores '' as NULL and returns NULL as ''. Use this for unique CharField. As long as this field is referenced in a migration, this definition must be kept. When upgrading to Django >= 1.11, it is possible to drop the methods: `from_db_value`, `to_python` and `get_prep_value`. Source: https://github.com/django-oscar/django-oscar/blob/1a2e8279161a396e70e44339d7206f25355b33a3/src/oscar/models/fields/__init__.py#L94 """ description = "CharField that stores '' as NULL and returns NULL as ''" def __init__(self, *args, **kwargs): if not kwargs.get("null", True) or not kwargs.get("blank", True): raise ImproperlyConfigured("NullCharField implies 'null == blank == True'.") kwargs["null"] = kwargs["blank"] = True super().__init__(*args, **kwargs) def from_db_value(self, value, *args, **kwargs): return self.to_python(value) def to_python(self, *args, **kwargs): val = super().to_python(*args, **kwargs) return val if val is not None else "" def get_prep_value(self, *args, **kwargs): prepped = super().get_prep_value(*args, **kwargs) return prepped if prepped != "" else None def deconstruct(self): name, path, args, kwargs = super().deconstruct() del kwargs["null"] del kwargs["blank"] return name, path, args, kwargs