diff --git a/django/forms/fields.py b/django/forms/fields.py
index c7ed085..bc37701 100644
a
|
b
|
class Field(object):
|
53 | 53 | 'required': _('This field is required.'), |
54 | 54 | 'invalid': _('Enter a valid value.'), |
55 | 55 | } |
| 56 | empty_values = list(validators.EMPTY_VALUES) |
56 | 57 | |
57 | 58 | # Tracks each time a Field instance is created. Used to retain order. |
58 | 59 | creation_counter = 0 |
… |
… |
class Field(object):
|
125 | 126 | return value |
126 | 127 | |
127 | 128 | def validate(self, value): |
128 | | if value in validators.EMPTY_VALUES and self.required: |
| 129 | if value in self.empty_values and self.required: |
129 | 130 | raise ValidationError(self.error_messages['required']) |
130 | 131 | |
131 | 132 | def run_validators(self, value): |
132 | | if value in validators.EMPTY_VALUES: |
| 133 | if value in self.empty_values: |
133 | 134 | return |
134 | 135 | errors = [] |
135 | 136 | for v in self.validators: |
… |
… |
class CharField(Field):
|
210 | 211 | |
211 | 212 | def to_python(self, value): |
212 | 213 | "Returns a Unicode object." |
213 | | if value in validators.EMPTY_VALUES: |
| 214 | if value in self.empty_values: |
214 | 215 | return '' |
215 | 216 | return smart_text(value) |
216 | 217 | |
… |
… |
class IntegerField(Field):
|
244 | 245 | of int(). Returns None for empty values. |
245 | 246 | """ |
246 | 247 | value = super(IntegerField, self).to_python(value) |
247 | | if value in validators.EMPTY_VALUES: |
| 248 | if value in self.empty_values: |
248 | 249 | return None |
249 | 250 | if self.localize: |
250 | 251 | value = formats.sanitize_separators(value) |
… |
… |
class FloatField(IntegerField):
|
275 | 276 | of float(). Returns None for empty values. |
276 | 277 | """ |
277 | 278 | value = super(IntegerField, self).to_python(value) |
278 | | if value in validators.EMPTY_VALUES: |
| 279 | if value in self.empty_values: |
279 | 280 | return None |
280 | 281 | if self.localize: |
281 | 282 | value = formats.sanitize_separators(value) |
… |
… |
class DecimalField(IntegerField):
|
311 | 312 | than max_digits in the number, and no more than decimal_places digits |
312 | 313 | after the decimal point. |
313 | 314 | """ |
314 | | if value in validators.EMPTY_VALUES: |
| 315 | if value in self.empty_values: |
315 | 316 | return None |
316 | 317 | if self.localize: |
317 | 318 | value = formats.sanitize_separators(value) |
… |
… |
class DecimalField(IntegerField):
|
324 | 325 | |
325 | 326 | def validate(self, value): |
326 | 327 | super(DecimalField, self).validate(value) |
327 | | if value in validators.EMPTY_VALUES: |
| 328 | if value in self.empty_values: |
328 | 329 | return |
329 | 330 | # Check for NaN, Inf and -Inf values. We can't compare directly for NaN, |
330 | 331 | # since it is never equal to itself. However, NaN is the only value that |
… |
… |
class DateField(BaseTemporalField):
|
401 | 402 | Validates that the input can be converted to a date. Returns a Python |
402 | 403 | datetime.date object. |
403 | 404 | """ |
404 | | if value in validators.EMPTY_VALUES: |
| 405 | if value in self.empty_values: |
405 | 406 | return None |
406 | 407 | if isinstance(value, datetime.datetime): |
407 | 408 | return value.date() |
… |
… |
class TimeField(BaseTemporalField):
|
425 | 426 | Validates that the input can be converted to a time. Returns a Python |
426 | 427 | datetime.time object. |
427 | 428 | """ |
428 | | if value in validators.EMPTY_VALUES: |
| 429 | if value in self.empty_values: |
429 | 430 | return None |
430 | 431 | if isinstance(value, datetime.time): |
431 | 432 | return value |
… |
… |
class DateTimeField(BaseTemporalField):
|
451 | 452 | Validates that the input can be converted to a datetime. Returns a |
452 | 453 | Python datetime.datetime object. |
453 | 454 | """ |
454 | | if value in validators.EMPTY_VALUES: |
| 455 | if value in self.empty_values: |
455 | 456 | return None |
456 | 457 | if isinstance(value, datetime.datetime): |
457 | 458 | return from_current_timezone(value) |
… |
… |
class DateTimeField(BaseTemporalField):
|
463 | 464 | # components: date and time. |
464 | 465 | if len(value) != 2: |
465 | 466 | raise ValidationError(self.error_messages['invalid']) |
466 | | if value[0] in validators.EMPTY_VALUES and value[1] in validators.EMPTY_VALUES: |
| 467 | if value[0] in self.empty_values and value[1] in self.empty_values: |
467 | 468 | return None |
468 | 469 | value = '%s %s' % tuple(value) |
469 | 470 | result = super(DateTimeField, self).to_python(value) |
… |
… |
class FileField(Field):
|
531 | 532 | super(FileField, self).__init__(*args, **kwargs) |
532 | 533 | |
533 | 534 | def to_python(self, data): |
534 | | if data in validators.EMPTY_VALUES: |
| 535 | if data in self.empty_values: |
535 | 536 | return None |
536 | 537 | |
537 | 538 | # UploadedFile objects should have name and size attributes. |
… |
… |
class FileField(Field):
|
562 | 563 | return False |
563 | 564 | # If the field is required, clearing is not possible (the widget |
564 | 565 | # shouldn't return False data in that case anyway). False is not |
565 | | # in validators.EMPTY_VALUES; if a False value makes it this far |
| 566 | # in self.empty_value; if a False value makes it this far |
566 | 567 | # it should be validated from here on out as None (so it will be |
567 | 568 | # caught by the required check). |
568 | 569 | data = None |
… |
… |
class ChoiceField(Field):
|
763 | 764 | |
764 | 765 | def to_python(self, value): |
765 | 766 | "Returns a Unicode object." |
766 | | if value in validators.EMPTY_VALUES: |
| 767 | if value in self.empty_values: |
767 | 768 | return '' |
768 | 769 | return smart_text(value) |
769 | 770 | |
… |
… |
class TypedChoiceField(ChoiceField):
|
801 | 802 | """ |
802 | 803 | value = super(TypedChoiceField, self).to_python(value) |
803 | 804 | super(TypedChoiceField, self).validate(value) |
804 | | if value == self.empty_value or value in validators.EMPTY_VALUES: |
| 805 | if value == self.empty_value or value in self.empty_values: |
805 | 806 | return self.empty_value |
806 | 807 | try: |
807 | 808 | value = self.coerce(value) |
… |
… |
class TypedMultipleChoiceField(MultipleChoiceField):
|
864 | 865 | """ |
865 | 866 | value = super(TypedMultipleChoiceField, self).to_python(value) |
866 | 867 | super(TypedMultipleChoiceField, self).validate(value) |
867 | | if value == self.empty_value or value in validators.EMPTY_VALUES: |
| 868 | if value == self.empty_value or value in self.empty_values: |
868 | 869 | return self.empty_value |
869 | 870 | new_value = [] |
870 | 871 | for choice in value: |
… |
… |
class MultiValueField(Field):
|
945 | 946 | clean_data = [] |
946 | 947 | errors = ErrorList() |
947 | 948 | if not value or isinstance(value, (list, tuple)): |
948 | | if not value or not [v for v in value if v not in validators.EMPTY_VALUES]: |
| 949 | if not value or not [v for v in value if v not in self.empty_values]: |
949 | 950 | if self.required: |
950 | 951 | raise ValidationError(self.error_messages['required']) |
951 | 952 | else: |
… |
… |
class MultiValueField(Field):
|
957 | 958 | field_value = value[i] |
958 | 959 | except IndexError: |
959 | 960 | field_value = None |
960 | | if self.required and field_value in validators.EMPTY_VALUES: |
| 961 | if self.required and field_value in self.empty_values: |
961 | 962 | raise ValidationError(self.error_messages['required']) |
962 | 963 | try: |
963 | 964 | clean_data.append(field.clean(field_value)) |
… |
… |
class SplitDateTimeField(MultiValueField):
|
1071 | 1072 | if data_list: |
1072 | 1073 | # Raise a validation error if time or date is empty |
1073 | 1074 | # (possible if SplitDateTimeField has required=False). |
1074 | | if data_list[0] in validators.EMPTY_VALUES: |
| 1075 | if data_list[0] in self.empty_values: |
1075 | 1076 | raise ValidationError(self.error_messages['invalid_date']) |
1076 | | if data_list[1] in validators.EMPTY_VALUES: |
| 1077 | if data_list[1] in self.empty_values: |
1077 | 1078 | raise ValidationError(self.error_messages['invalid_time']) |
1078 | 1079 | result = datetime.datetime.combine(*data_list) |
1079 | 1080 | return from_current_timezone(result) |
… |
… |
class IPAddressField(CharField):
|
1087 | 1088 | default_validators = [validators.validate_ipv4_address] |
1088 | 1089 | |
1089 | 1090 | def to_python(self, value): |
1090 | | if value in EMPTY_VALUES: |
| 1091 | if value in self.empty_values: |
1091 | 1092 | return '' |
1092 | 1093 | return value.strip() |
1093 | 1094 | |
… |
… |
class GenericIPAddressField(CharField):
|
1103 | 1104 | super(GenericIPAddressField, self).__init__(*args, **kwargs) |
1104 | 1105 | |
1105 | 1106 | def to_python(self, value): |
1106 | | if value in validators.EMPTY_VALUES: |
| 1107 | if value in self.empty_values: |
1107 | 1108 | return '' |
1108 | 1109 | value = value.strip() |
1109 | 1110 | if value and ':' in value: |
diff --git a/django/forms/models.py b/django/forms/models.py
index 87fd546..7609bb7 100644
a
|
b
|
and database field objects.
|
6 | 6 | from __future__ import absolute_import, unicode_literals |
7 | 7 | |
8 | 8 | from django.core.exceptions import ValidationError, NON_FIELD_ERRORS, FieldError |
9 | | from django.core.validators import EMPTY_VALUES |
10 | 9 | from django.forms.fields import Field, ChoiceField |
11 | 10 | from django.forms.forms import BaseForm, get_declared_fields |
12 | 11 | from django.forms.formsets import BaseFormSet, formset_factory |
… |
… |
class BaseModelForm(BaseForm):
|
301 | 300 | else: |
302 | 301 | form_field = self.fields[field] |
303 | 302 | field_value = self.cleaned_data.get(field, None) |
304 | | if not f.blank and not form_field.required and field_value in EMPTY_VALUES: |
| 303 | if not f.blank and not form_field.required and field_value in form_field.empty_values: |
305 | 304 | exclude.append(f.name) |
306 | 305 | return exclude |
307 | 306 | |
… |
… |
class InlineForeignKeyField(Field):
|
880 | 879 | super(InlineForeignKeyField, self).__init__(*args, **kwargs) |
881 | 880 | |
882 | 881 | def clean(self, value): |
883 | | if value in EMPTY_VALUES: |
| 882 | if value in self.empty_values: |
884 | 883 | if self.pk_field: |
885 | 884 | return None |
886 | 885 | # if there is no value act as we did before. |
… |
… |
class ModelChoiceField(ChoiceField):
|
1000 | 999 | return super(ModelChoiceField, self).prepare_value(value) |
1001 | 1000 | |
1002 | 1001 | def to_python(self, value): |
1003 | | if value in EMPTY_VALUES: |
| 1002 | if value in self.empty_values: |
1004 | 1003 | return None |
1005 | 1004 | try: |
1006 | 1005 | key = self.to_field_name or 'pk' |
diff --git a/django/test/testcases.py b/django/test/testcases.py
index 345e4b1..44ddb62 100644
a
|
b
|
from django.core.management.color import no_style
|
27 | 27 | from django.core.servers.basehttp import (WSGIRequestHandler, WSGIServer, |
28 | 28 | WSGIServerException) |
29 | 29 | from django.core.urlresolvers import clear_url_caches |
30 | | from django.core.validators import EMPTY_VALUES |
31 | 30 | from django.db import connection, connections, DEFAULT_DB_ALIAS, transaction |
32 | 31 | from django.forms.fields import CharField |
33 | 32 | from django.http import QueryDict |
… |
… |
class SimpleTestCase(ut2.TestCase):
|
322 | 321 | raised error messages. |
323 | 322 | field_args: the args passed to instantiate the field |
324 | 323 | field_kwargs: the kwargs passed to instantiate the field |
325 | | empty_value: the expected clean output for inputs in EMPTY_VALUES |
| 324 | empty_value: the expected clean output for inputs in empty_values |
326 | 325 | |
327 | 326 | """ |
328 | 327 | if field_args is None: |
… |
… |
class SimpleTestCase(ut2.TestCase):
|
347 | 346 | self.assertEqual(context_manager.exception.messages, errors) |
348 | 347 | # test required inputs |
349 | 348 | error_required = [force_text(required.error_messages['required'])] |
350 | | for e in EMPTY_VALUES: |
| 349 | for e in required.empty_values: |
351 | 350 | with self.assertRaises(ValidationError) as context_manager: |
352 | 351 | required.clean(e) |
353 | 352 | self.assertEqual(context_manager.exception.messages, |
diff --git a/docs/topics/testing/overview.txt b/docs/topics/testing/overview.txt
index 3b2babd..b917086 100644
a
|
b
|
your test suite.
|
1480 | 1480 | error messages. |
1481 | 1481 | :param field_args: the args passed to instantiate the field. |
1482 | 1482 | :param field_kwargs: the kwargs passed to instantiate the field. |
1483 | | :param empty_value: the expected clean output for inputs in ``EMPTY_VALUES``. |
| 1483 | :param empty_value: the expected clean output for inputs in ``empty_values``. |
1484 | 1484 | |
1485 | 1485 | For example, the following code tests that an ``EmailField`` accepts |
1486 | 1486 | "a@a.com" as a valid email address, but rejects "aaa" with a reasonable |
diff --git a/tests/forms_tests/tests/forms.py b/tests/forms_tests/tests/forms.py
index f856e30..1f65045 100644
a
|
b
|
class FormsTestCase(TestCase):
|
1797 | 1797 | form = NameForm(data={'name' : ['fname', 'lname']}) |
1798 | 1798 | self.assertTrue(form.is_valid()) |
1799 | 1799 | self.assertEqual(form.cleaned_data, {'name' : 'fname lname'}) |
| 1800 | |
| 1801 | def test_empty_values(self): |
| 1802 | class OldFakeJSONField(forms.Field): |
| 1803 | def to_python(self, value): |
| 1804 | if value in [None, '']: |
| 1805 | return None |
| 1806 | # Fake json.loads. |
| 1807 | if value == '{}': |
| 1808 | return {} |
| 1809 | raise NotImplementedError |
| 1810 | |
| 1811 | def prepare_value(self, value): |
| 1812 | if value in [None, '']: |
| 1813 | return '' |
| 1814 | # Fake json.dumps |
| 1815 | if value == {}: |
| 1816 | return '{}' |
| 1817 | raise NotImplementedError |
| 1818 | |
| 1819 | class NewFakeJSONField(OldFakeJSONField): |
| 1820 | empty_values = [None, ''] |
| 1821 | |
| 1822 | class FakeJSONForm(forms.Form): |
| 1823 | old = OldFakeJSONField() |
| 1824 | new = NewFakeJSONField() |
| 1825 | form = FakeJSONForm(data={'old': '{}', 'new': '{}'}); |
| 1826 | form.full_clean() |
| 1827 | self.assertEqual(form.errors, {'old': ['This field is required.']}) |
| 1828 | self.assertEqual(form.cleaned_data, {'new' : {}}) |