diff options
| author | Stephen Burrows <stephen.r.burrows@gmail.com> | 2014-05-06 18:14:06 -0700 |
|---|---|---|
| committer | Claude Paroz <claude@2xlibre.net> | 2014-05-10 10:58:51 +0200 |
| commit | 0c198035e958a3caa0bd1e0fd9f419bf1308399d (patch) | |
| tree | 5ac1c255c7e95e529949ceb8fe59d2ae05d009e1 | |
| parent | 8a090c21f10c503dd5f29885e78bfb0cb5588ba4 (diff) | |
[1.7.x] Fixed #22502 -- Fixed microseconds/default/form interaction
Made explicit lack of microsecond handling by built-in datetime form
fields. Used that explicitness to appropriately nix microsecond
values in bound fields. Thanks Claude Paroz for the review.
Backport of a5de0df58 from master.
| -rw-r--r-- | AUTHORS | 1 | ||||
| -rw-r--r-- | django/forms/forms.py | 6 | ||||
| -rw-r--r-- | django/forms/widgets.py | 2 | ||||
| -rw-r--r-- | tests/forms_tests/tests/test_forms.py | 29 |
4 files changed, 35 insertions, 3 deletions
@@ -136,6 +136,7 @@ answer newbie questions, and generally made Django that much better: btoll@bestweb.net Jonathan Buchanan <jonathan.buchanan@gmail.com> Jacob Burch <jacobburch@gmail.com> + Stephen Burrows <stephen.r.burrows@gmail.com> Max Burstein <http://maxburstein.com> Keith Bussell <kbussell@gmail.com> C8E diff --git a/django/forms/forms.py b/django/forms/forms.py index 5362fd5aaf..2cfd4ec241 100644 --- a/django/forms/forms.py +++ b/django/forms/forms.py @@ -6,6 +6,7 @@ from __future__ import unicode_literals from collections import OrderedDict import copy +import datetime import warnings from django.core.exceptions import ValidationError, NON_FIELD_ERRORS @@ -590,6 +591,11 @@ class BoundField(object): data = self.form.initial.get(self.name, self.field.initial) if callable(data): data = data() + # If this is an auto-generated default date, nix the + # microseconds for standardized handling. See #22502. + if (isinstance(data, (datetime.datetime, datetime.time)) and + not getattr(self.field.widget, 'supports_microseconds', True)): + data = data.replace(microsecond=0) else: data = self.field.bound_data( self.data, self.form.initial.get(self.name, self.field.initial) diff --git a/django/forms/widgets.py b/django/forms/widgets.py index 53003749d3..27b056301d 100644 --- a/django/forms/widgets.py +++ b/django/forms/widgets.py @@ -429,6 +429,7 @@ class Textarea(Widget): class DateTimeBaseInput(TextInput): format_key = '' + supports_microseconds = False def __init__(self, attrs=None, format=None): super(DateTimeBaseInput, self).__init__(attrs) @@ -863,6 +864,7 @@ class SplitDateTimeWidget(MultiWidget): """ A Widget that splits datetime input into two <input type="text"> boxes. """ + supports_microseconds = False def __init__(self, attrs=None, date_format=None, time_format=None): widgets = (DateInput(attrs=attrs, format=date_format), diff --git a/tests/forms_tests/tests/test_forms.py b/tests/forms_tests/tests/test_forms.py index ea2858200c..a2ffc3b1fe 100644 --- a/tests/forms_tests/tests/test_forms.py +++ b/tests/forms_tests/tests/test_forms.py @@ -10,10 +10,10 @@ from django.core.files.uploadedfile import SimpleUploadedFile from django.core.validators import RegexValidator from django.forms import ( BooleanField, CharField, CheckboxSelectMultiple, ChoiceField, DateField, - EmailField, FileField, FloatField, Form, forms, HiddenInput, IntegerField, - MultipleChoiceField, MultipleHiddenInput, MultiValueField, + DateTimeField, EmailField, FileField, FloatField, Form, forms, HiddenInput, + IntegerField, MultipleChoiceField, MultipleHiddenInput, MultiValueField, NullBooleanField, PasswordInput, RadioSelect, Select, SplitDateTimeField, - Textarea, TextInput, ValidationError, widgets, + Textarea, TextInput, TimeField, ValidationError, widgets ) from django.forms.utils import ErrorList from django.http import QueryDict @@ -1287,6 +1287,29 @@ class FormsTestCase(TestCase): self.assertEqual(bound['password'].value(), 'foo') self.assertEqual(unbound['password'].value(), None) + def test_initial_datetime_values(self): + now = datetime.datetime.now() + # Nix microseconds (since they should be ignored). #22502 + now_no_ms = now.replace(microsecond=0) + if now == now_no_ms: + now = now.replace(microsecond=1) + + def delayed_now(): + return now + + def delayed_now_time(): + return now.time() + + class DateTimeForm(Form): + auto_timestamp = DateTimeField(initial=delayed_now) + auto_time_only = TimeField(initial=delayed_now_time) + supports_microseconds = DateTimeField(initial=delayed_now, widget=TextInput) + + unbound = DateTimeForm() + self.assertEqual(unbound['auto_timestamp'].value(), now_no_ms) + self.assertEqual(unbound['auto_time_only'].value(), now_no_ms.time()) + self.assertEqual(unbound['supports_microseconds'].value(), now) + def test_help_text(self): # You can specify descriptive text for a field by using the 'help_text' argument) class UserRegistration(Form): |
