Commit 267dc4ad authored by Jon Dufresne's avatar Jon Dufresne Committed by Tim Graham
Browse files

Fixed #4136 -- Made ModelForm save empty values for nullable CharFields as NULL.

Previously, empty values were saved as strings.
parent f2c0eb19
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -13,8 +13,8 @@ from django.core.exceptions import (
    ObjectDoesNotExist, ValidationError,
)
from django.db import (
    DEFAULT_DB_ALIAS, DJANGO_VERSION_PICKLE_KEY, DatabaseError, connections,
    router, transaction,
    DEFAULT_DB_ALIAS, DJANGO_VERSION_PICKLE_KEY, DatabaseError, connection,
    connections, router, transaction,
)
from django.db.models import signals
from django.db.models.constants import LOOKUP_SEP
@@ -1087,7 +1087,9 @@ class Model(six.with_metaclass(ModelBase)):
            for field_name in unique_check:
                f = self._meta.get_field(field_name)
                lookup_value = getattr(self, f.attname)
                if lookup_value is None:
                # TODO: Handle multiple backends with different feature flags.
                if (lookup_value is None or
                        (lookup_value == '' and connection.features.interprets_empty_strings_as_nulls)):
                    # no value, skip the lookup
                    continue
                if f.primary_key and not self._state.adding:
+3 −0
Original line number Diff line number Diff line
@@ -1086,6 +1086,9 @@ class CharField(Field):
        # will be validated twice. This is considered acceptable since we want
        # the value in the form field (to pass into widget for example).
        defaults = {'max_length': self.max_length}
        # TODO: Handle multiple backends with different feature flags.
        if self.null and not connection.features.interprets_empty_strings_as_nulls:
            defaults['empty_value'] = None
        defaults.update(kwargs)
        return super(CharField, self).formfield(**defaults)

+3 −2
Original line number Diff line number Diff line
@@ -214,10 +214,11 @@ class Field(object):


class CharField(Field):
    def __init__(self, max_length=None, min_length=None, strip=True, *args, **kwargs):
    def __init__(self, max_length=None, min_length=None, strip=True, empty_value='', *args, **kwargs):
        self.max_length = max_length
        self.min_length = min_length
        self.strip = strip
        self.empty_value = empty_value
        super(CharField, self).__init__(*args, **kwargs)
        if min_length is not None:
            self.validators.append(validators.MinLengthValidator(int(min_length)))
@@ -227,7 +228,7 @@ class CharField(Field):
    def to_python(self, value):
        "Returns a Unicode object."
        if value in self.empty_values:
            return ''
            return self.empty_value
        value = force_text(value)
        if self.strip:
            value = value.strip()
+7 −1
Original line number Diff line number Diff line
@@ -361,7 +361,7 @@ For each field, we describe the default widget used if you don't specify
.. class:: CharField(**kwargs)

    * Default widget: :class:`TextInput`
    * Empty value: ``''`` (an empty string)
    * Empty value: Whatever you've given as :attr:`empty_value`.
    * Normalizes to: A Unicode object.
    * Validates ``max_length`` or ``min_length``, if they are provided.
      Otherwise, all inputs are valid.
@@ -380,6 +380,12 @@ For each field, we describe the default widget used if you don't specify
       If ``True`` (default), the value will be stripped of leading and
       trailing whitespace.

    .. attribute:: empty_value

       .. versionadded:: 1.11

       The value to use to represent "empty". Defaults to an empty string.

``ChoiceField``
---------------

+5 −3
Original line number Diff line number Diff line
@@ -43,11 +43,13 @@ If ``True``, Django will store empty values as ``NULL`` in the database. Default
is ``False``.

Avoid using :attr:`~Field.null` on string-based fields such as
:class:`CharField` and :class:`TextField` because empty string values will
always be stored as empty strings, not as ``NULL``. If a string-based field has
:class:`CharField` and :class:`TextField`. If a string-based field has
``null=True``, that means it has two possible values for "no data": ``NULL``,
and the empty string. In most cases, it's redundant to have two possible values
for "no data;" the Django convention is to use the empty string, not ``NULL``.
for "no data;" the Django convention is to use the empty string, not
``NULL``. One exception is when a :class:`CharField` has both ``unique=True``
and ``blank=True`` set. In this situation, ``null=True`` is required to avoid
unique constraint violations when saving multiple objects with blank values.

For both string-based and non-string-based fields, you will also need to
set ``blank=True`` if you wish to permit empty values in forms, as the
Loading