Ticket #5714: 5714.diff

File 5714.diff, 9.2 KB (added by Chris Beaven, 13 years ago)
  • django/forms/fields.py

    diff --git a/django/forms/fields.py b/django/forms/fields.py
    index 4d7728f..eb6ef22 100644
    a b from django.core import validators  
    1919import django.utils.copycompat as copy
    2020from django.utils import formats
    2121from django.utils.translation import ugettext_lazy as _
    22 from django.utils.encoding import smart_unicode, smart_str
     22from django.utils.encoding import smart_unicode, smart_str, force_unicode
    2323from django.utils.functional import lazy
    2424
    2525# Provide this import for backwards compatibility.
    class DecimalField(Field):  
    336336            raise ValidationError(self.error_messages['max_whole_digits'] % (self.max_digits - self.decimal_places))
    337337        return value
    338338
    339 class DateField(Field):
     339class BaseTemporalField(Field):
     340    def __init__(self, input_formats=None, *args, **kwargs):
     341        super(BaseTemporalField, self).__init__(*args, **kwargs)
     342        self.input_formats = input_formats
     343
     344    def to_python(self, value):
     345        # Try to coerce the value to unicode.
     346        unicode_value = force_unicode(value, strings_only=True)
     347        if isinstance(unicode_value, unicode):
     348            value = unicode_value.strip()
     349        # If empty, return None
     350        if value in validators.EMPTY_VALUES:
     351            return None
     352        # If unicode, try to strptime against each import format.
     353        if isinstance(value, unicode):
     354            for format in self.get_input_formats():
     355                try:
     356                    return self.strptime(value, format)
     357                except ValueError:
     358                    continue
     359        raise ValidationError(self.error_messages['invalid'])
     360
     361    def get_input_formats(self):
     362        return self.input_formats or []
     363
     364    def strptime(self, value, format):
     365        raise NotImplementedError('Subclasses must define this method.')
     366
     367class DateField(BaseTemporalField):
    340368    widget = DateInput
    341369    default_error_messages = {
    342370        'invalid': _(u'Enter a valid date.'),
    343371    }
    344372
    345     def __init__(self, input_formats=None, *args, **kwargs):
    346         super(DateField, self).__init__(*args, **kwargs)
    347         self.input_formats = input_formats
    348 
    349373    def to_python(self, value):
    350374        """
    351375        Validates that the input can be converted to a date. Returns a Python
    352376        datetime.date object.
    353377        """
    354         if value in validators.EMPTY_VALUES:
    355             return None
    356378        if isinstance(value, datetime.datetime):
    357379            return value.date()
    358380        if isinstance(value, datetime.date):
    359381            return value
    360         for format in self.input_formats or formats.get_format('DATE_INPUT_FORMATS'):
    361             try:
    362                 return datetime.date(*time.strptime(value, format)[:3])
    363             except ValueError:
    364                 continue
    365         raise ValidationError(self.error_messages['invalid'])
     382        return super(DateField, self).to_python(value)
     383
     384    def get_input_formats(self):
     385        return self.input_formats or formats.get_format('DATE_INPUT_FORMATS')
     386
     387    def strptime(self, value, format):
     388        return datetime.date(*time.strptime(value, format)[:3])
    366389
    367 class TimeField(Field):
     390class TimeField(BaseTemporalField):
    368391    widget = TimeInput
    369392    default_error_messages = {
    370393        'invalid': _(u'Enter a valid time.')
    371394    }
    372395
    373     def __init__(self, input_formats=None, *args, **kwargs):
    374         super(TimeField, self).__init__(*args, **kwargs)
    375         self.input_formats = input_formats
    376 
    377396    def to_python(self, value):
    378397        """
    379398        Validates that the input can be converted to a time. Returns a Python
    380399        datetime.time object.
    381400        """
    382         if value in validators.EMPTY_VALUES:
    383             return None
    384401        if isinstance(value, datetime.time):
    385402            return value
    386         for format in self.input_formats or formats.get_format('TIME_INPUT_FORMATS'):
    387             try:
    388                 return datetime.time(*time.strptime(value, format)[3:6])
    389             except ValueError:
    390                 continue
    391         raise ValidationError(self.error_messages['invalid'])
     403        return super(TimeField, self).to_python(value)
     404
     405    def get_input_formats(self):
     406        return self.input_formats or formats.get_format('TIME_INPUT_FORMATS')
     407
     408    def strptime(self, value, format):
     409        return datetime.time(*time.strptime(value, format)[3:6])
    392410
    393 class DateTimeField(Field):
     411class DateTimeField(BaseTemporalField):
    394412    widget = DateTimeInput
    395413    default_error_messages = {
    396414        'invalid': _(u'Enter a valid date/time.'),
    397415    }
    398416
    399     def __init__(self, input_formats=None, *args, **kwargs):
    400         super(DateTimeField, self).__init__(*args, **kwargs)
    401         self.input_formats = input_formats
    402 
    403417    def to_python(self, value):
    404418        """
    405419        Validates that the input can be converted to a datetime. Returns a
    406420        Python datetime.datetime object.
    407421        """
    408         if value in validators.EMPTY_VALUES:
    409             return None
    410422        if isinstance(value, datetime.datetime):
    411423            return value
    412424        if isinstance(value, datetime.date):
    class DateTimeField(Field):  
    419431            if value[0] in validators.EMPTY_VALUES and value[1] in validators.EMPTY_VALUES:
    420432                return None
    421433            value = '%s %s' % tuple(value)
    422         for format in self.input_formats or formats.get_format('DATETIME_INPUT_FORMATS'):
    423             try:
    424                 return datetime.datetime(*time.strptime(value, format)[:6])
    425             except ValueError:
    426                 continue
    427         raise ValidationError(self.error_messages['invalid'])
     434        return super(DateTimeField, self).to_python(value)
     435
     436    def get_input_formats(self):
     437        return (self.input_formats or
     438                formats.get_format('DATETIME_INPUT_FORMATS'))
     439
     440    def strptime(self, value, format):
     441        return datetime.datetime(*time.strptime(value, format)[:6])
    428442
    429443class RegexField(CharField):
    430444    def __init__(self, regex, max_length=None, min_length=None, error_message=None, *args, **kwargs):
  • tests/regressiontests/forms/tests/fields.py

    diff --git a/tests/regressiontests/forms/tests/fields.py b/tests/regressiontests/forms/tests/fields.py
    index 576a9c3..dad6003 100644
    a b class FieldsTests(TestCase):  
    333333        self.assertRaisesErrorWithMessage(ValidationError, "[u'Enter a valid date.']", f.clean, '10/25/2006')
    334334        self.assertRaisesErrorWithMessage(ValidationError, "[u'Enter a valid date.']", f.clean, '10/25/06')
    335335
     336    def test_datefield_4(self):
     337        # Test whitespace stripping behavior (#5714)
     338        f = DateField()
     339        self.assertEqual(datetime.date(2006, 10, 25), f.clean(' 10/25/2006 '))
     340        self.assertEqual(datetime.date(2006, 10, 25), f.clean(' 10/25/06 '))
     341        self.assertEqual(datetime.date(2006, 10, 25), f.clean(' Oct 25   2006 '))
     342        self.assertEqual(datetime.date(2006, 10, 25), f.clean(' October  25 2006 '))
     343        self.assertEqual(datetime.date(2006, 10, 25), f.clean(' October 25, 2006 '))
     344        self.assertEqual(datetime.date(2006, 10, 25), f.clean(' 25 October 2006 '))
     345        self.assertRaisesErrorWithMessage(ValidationError, "[u'This field is required.']", f.clean, '   ')
     346
    336347    # TimeField ###################################################################
    337348
    338349    def test_timefield_1(self):
    class FieldsTests(TestCase):  
    352363        self.assertEqual(datetime.time(16, 25), f.clean('4:25 PM'))
    353364        self.assertRaisesErrorWithMessage(ValidationError, "[u'Enter a valid time.']", f.clean, '14:30:45')
    354365
     366    def test_timefield_3(self):
     367        f = TimeField()
     368        # Test whitespace stripping behavior (#5714)
     369        self.assertEqual(datetime.time(14, 25), f.clean(' 14:25 '))
     370        self.assertEqual(datetime.time(14, 25, 59), f.clean(' 14:25:59 '))
     371        self.assertRaisesErrorWithMessage(ValidationError, "[u'This field is required.']", f.clean, '   ')
     372
    355373    # DateTimeField ###############################################################
    356374
    357375    def test_datetimefield_1(self):
    class FieldsTests(TestCase):  
    391409        self.assertEqual(None, f.clean(''))
    392410        self.assertEqual('None', repr(f.clean('')))
    393411
     412    def test_datetimefield_4(self):
     413        f = DateTimeField()
     414        # Test whitespace stripping behavior (#5714)
     415        self.assertEqual(datetime.datetime(2006, 10, 25, 14, 30, 45), f.clean(' 2006-10-25   14:30:45 '))
     416        self.assertEqual(datetime.datetime(2006, 10, 25, 0, 0), f.clean(' 2006-10-25 '))
     417        self.assertEqual(datetime.datetime(2006, 10, 25, 14, 30, 45), f.clean(' 10/25/2006 14:30:45 '))
     418        self.assertEqual(datetime.datetime(2006, 10, 25, 14, 30), f.clean(' 10/25/2006 14:30 '))
     419        self.assertEqual(datetime.datetime(2006, 10, 25, 0, 0), f.clean(' 10/25/2006 '))
     420        self.assertEqual(datetime.datetime(2006, 10, 25, 14, 30, 45), f.clean(' 10/25/06 14:30:45 '))
     421        self.assertEqual(datetime.datetime(2006, 10, 25, 0, 0), f.clean(' 10/25/06 '))
     422        self.assertRaisesErrorWithMessage(ValidationError, "[u'This field is required.']", f.clean, '   ')
     423
    394424    # RegexField ##################################################################
    395425
    396426    def test_regexfield_1(self):
Back to Top