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:
parent
8a9d54aa69
commit
cb15231888
|
@ -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 "
|
||||||
|
|
|
@ -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
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
|
|
|
@ -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``
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue