Fixed #21798 -- Added check for DateTime mutually exclusive options

Added DateTimeCheckMixin to avoid the use of default, auto_now, and
auto_now_add options together. Added the fields.E151 Error that is raised
if one or more of these options are used together.
This commit is contained in:
Daniel Pyrathon 2014-03-13 11:32:20 +00:00 committed by Tim Graham
parent 8a9d54aa69
commit cb15231888
4 changed files with 64 additions and 2 deletions

View File

@ -1074,7 +1074,37 @@ class CommaSeparatedIntegerField(CharField):
return super(CommaSeparatedIntegerField, self).formfield(**defaults) return super(CommaSeparatedIntegerField, self).formfield(**defaults)
class DateField(Field): class DateTimeCheckMixin(object):
def check(self, **kwargs):
errors = super(DateTimeCheckMixin, self).check(**kwargs)
errors.extend(self._check_mutually_exclusive_options())
return errors
def _check_mutually_exclusive_options(self):
# auto_now, auto_now_add, and default are mutually exclusive
# options. The use of more than one of these options together
# will trigger an Error
mutually_exclusive_options = [self.auto_now_add, self.auto_now,
self.has_default()]
enabled_options = [option not in (None, False)
for option in mutually_exclusive_options].count(True)
if enabled_options > 1:
return [
checks.Error(
"The options auto_now, auto_now_add, and default "
"are mutually exclusive. Only one of these options "
"may be present.",
hint=None,
obj=self,
id='fields.E151',
)
]
else:
return []
class DateField(DateTimeCheckMixin, Field):
empty_strings_allowed = False empty_strings_allowed = False
default_error_messages = { default_error_messages = {
'invalid': _("'%(value)s' value has an invalid date format. It must be " 'invalid': _("'%(value)s' value has an invalid date format. It must be "
@ -1887,7 +1917,7 @@ class TextField(Field):
return super(TextField, self).formfield(**defaults) return super(TextField, self).formfield(**defaults)
class TimeField(Field): class TimeField(DateTimeCheckMixin, Field):
empty_strings_allowed = False empty_strings_allowed = False
default_error_messages = { default_error_messages = {
'invalid': _("'%(value)s' value has an invalid format. It must be in " 'invalid': _("'%(value)s' value has an invalid format. It must be in "

View File

@ -67,6 +67,7 @@ Fields
* **fields.E134**: ``max_digits`` must be greater or equal to ``decimal_places``. * **fields.E134**: ``max_digits`` must be greater or equal to ``decimal_places``.
* **fields.E140**: FilePathFields must have either ``allow_files`` or ``allow_folders`` set to True. * **fields.E140**: FilePathFields must have either ``allow_files`` or ``allow_folders`` set to True.
* **fields.E150**: GenericIPAddressFields cannot accept blank values if null values are not allowed, as blank values are stored as nulls. * **fields.E150**: GenericIPAddressFields cannot accept blank values if null values are not allowed, as blank values are stored as nulls.
* **fields.E151**: The options ``auto_now``, ``auto_now_add``, and ``default`` are mutually exclusive. Only one of these options may be present.
File Fields File Fields
~~~~~~~~~~~ ~~~~~~~~~~~

View File

@ -477,6 +477,9 @@ The default form widget for this field is a
and a shortcut for "Today". Includes an additional ``invalid_date`` error and a shortcut for "Today". Includes an additional ``invalid_date`` error
message key. message key.
The options ``auto_now_add``, ``auto_now``, and ``default`` are mutually exclusive.
Any combination of these options will result in an error.
.. note:: .. note::
As currently implemented, setting ``auto_now`` or ``auto_now_add`` to As currently implemented, setting ``auto_now`` or ``auto_now_add`` to
``True`` will cause the field to have ``editable=False`` and ``blank=True`` ``True`` will cause the field to have ``editable=False`` and ``blank=True``

View File

@ -1,6 +1,7 @@
# -*- encoding: utf-8 -*- # -*- encoding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
from datetime import datetime
import unittest import unittest
from django.core.checks import Error from django.core.checks import Error
@ -399,3 +400,30 @@ class ImageFieldTests(IsolatedModelsTestCase):
), ),
] ]
self.assertEqual(errors, expected) self.assertEqual(errors, expected)
class DateFieldTests(IsolatedModelsTestCase):
def test_auto_now_and_auto_now_add_raise_error(self):
dn = datetime.now
mutually_exclusive_combinations = (
(True, True, dn),
(True, False, dn),
(False, True, dn),
(True, True, None)
)
for auto_now, auto_now_add, default in mutually_exclusive_combinations:
field = models.DateTimeField(name="field", auto_now=auto_now,
auto_now_add=auto_now_add,
default=default)
expected = [Error(
"The options auto_now, auto_now_add, and default "
"are mutually exclusive. Only one of these options "
"may be present.",
hint=None,
obj=field,
id='fields.E151',
)]
checks = field.check()
self.assertEqual(checks, expected)