Fixed #28474 -- Made DurationField raise ValidationError for inputs that raised OverflowError.

This commit is contained in:
Srinivas Reddy Thatiparthy 2017-08-08 20:32:08 +05:30 committed by Tim Graham
parent 81e357a7e1
commit 55b5393bd2
4 changed files with 26 additions and 3 deletions

View File

@ -740,6 +740,7 @@ answer newbie questions, and generally made Django that much better:
sloonz <simon.lipp@insa-lyon.fr> sloonz <simon.lipp@insa-lyon.fr>
smurf@smurf.noris.de smurf@smurf.noris.de
sopel sopel
Srinivas Reddy Thatiparthy <thatiparthysreenivas@gmail.com>
Stanislas Guerra <stan@slashdev.me> Stanislas Guerra <stan@slashdev.me>
Stanislaus Madueke Stanislaus Madueke
starrynight <cmorgh@gmail.com> starrynight <cmorgh@gmail.com>

View File

@ -469,6 +469,12 @@ class DateTimeField(BaseTemporalField):
class DurationField(Field): class DurationField(Field):
default_error_messages = { default_error_messages = {
'invalid': _('Enter a valid duration.'), 'invalid': _('Enter a valid duration.'),
'overflow': _(
'The number of days must be between {min_days} and {max_days}.'.format(
min_days=datetime.timedelta.min.days,
max_days=datetime.timedelta.max.days,
)
)
} }
def prepare_value(self, value): def prepare_value(self, value):
@ -481,7 +487,10 @@ class DurationField(Field):
return None return None
if isinstance(value, datetime.timedelta): if isinstance(value, datetime.timedelta):
return value return value
value = parse_duration(str(value)) try:
value = parse_duration(str(value))
except OverflowError:
raise ValidationError(self.error_messages['overflow'], code='overflow')
if value is None: if value is None:
raise ValidationError(self.error_messages['invalid'], code='invalid') raise ValidationError(self.error_messages['invalid'], code='invalid')
return value return value

View File

@ -566,8 +566,9 @@ For each field, we describe the default widget used if you don't specify
* Empty value: ``None`` * Empty value: ``None``
* Normalizes to: A Python :class:`~python:datetime.timedelta`. * Normalizes to: A Python :class:`~python:datetime.timedelta`.
* Validates that the given value is a string which can be converted into a * Validates that the given value is a string which can be converted into a
``timedelta``. ``timedelta``. The value must be between :attr:`datetime.timedelta.min`
* Error message keys: ``required``, ``invalid``. and :attr:`datetime.timedelta.max`.
* Error message keys: ``required``, ``invalid``, ``overflow``.
Accepts any format understood by Accepts any format understood by
:func:`~django.utils.dateparse.parse_duration`. :func:`~django.utils.dateparse.parse_duration`.

View File

@ -1,5 +1,6 @@
import datetime import datetime
from django.core.exceptions import ValidationError
from django.forms import DurationField from django.forms import DurationField
from django.test import SimpleTestCase from django.test import SimpleTestCase
from django.utils.duration import duration_string from django.utils.duration import duration_string
@ -19,6 +20,17 @@ class DurationFieldTest(FormFieldAssertionsMixin, SimpleTestCase):
f.clean('1 1:15:30.3') f.clean('1 1:15:30.3')
) )
def test_overflow(self):
msg = "The number of days must be between {min_days} and {max_days}.".format(
min_days=datetime.timedelta.min.days,
max_days=datetime.timedelta.max.days,
)
f = DurationField()
with self.assertRaisesMessage(ValidationError, msg):
f.clean('1000000000 00:00:00')
with self.assertRaisesMessage(ValidationError, msg):
f.clean('-1000000000 00:00:00')
def test_durationfield_render(self): def test_durationfield_render(self):
self.assertWidgetRendersTo( self.assertWidgetRendersTo(
DurationField(initial=datetime.timedelta(hours=1)), DurationField(initial=datetime.timedelta(hours=1)),