Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Bower components Debian packages RPM packages NuGet packages

nickfrez / unb-djutils   python

Repository URL to install this package:

Version: 0.0.24 

/ unb_djutils / fields / nullable.py

from django.core import exceptions
from django.db import models


class NullCharField(models.CharField):
  description = "CharField that transparently stores NULL for empty strings."
  __metaclass__ = models.SubfieldBase  # this ensures to_python will be called

  def to_python(self, value):
    # Is this the value right out of the db, or an instance? If an instance,
    # just return the instance.
    if isinstance(value, models.CharField):
      return value
    return value or ''  # Transform NULLs to empty strings.

  def get_prep_value(self, value):
    return value or None  # Transform empty strings to NULLs.


class NullEmailField(models.EmailField):
  description = "EmailField that transparently stores NULL for empty strings."
  __metaclass__ = models.SubfieldBase

  def to_python(self, value):
    if isinstance(value, models.EmailField):
      return value
    return value or ''

  def get_prep_value(self, value):
    return value or None


class NullTrueField(models.NullBooleanField):
  """Allow only True or NULL (silently coerce False -> NULL).

  This field type is useful when you have a field that you only want to allow 1
  of.  For example, a "primary" email address.

      class Email(models.Model):
        user = models.ForeignKey('auth.User')
        primary = NullTrueField()

        class Meta:
          unique_together = ('user', 'primary')

  By adding the ``unique_together`` constraint, we can enforce a single primary
  email address per user (since NULL != NULL).
  """
  description = "Boolean, Either True or None (no False allowed)."
  __metaclass__ = models.SubfieldBase

  def to_python(self, value):
    """Handle True/None normally, silently coerce False to None"""
    if value is None:
      return None
    if value is True:
      return True
    if value in ('None',):
      return None
    if value in ('t', 'True', '1'):
      return True

    # Coerce False -> None
    if value is False:
      return None
    if value in ('f', 'False', '0'):
      return None

    raise exceptions.ValidationError(
      self.error_messages['invalid'],
      code='invalid',
      params={'value': value},
    )

  def get_prep_value(self, value):
    value = super(NullTrueField, self).get_prep_value(value)
    if bool(value):
      return True
    return None