Author: kmtracey
Date: 2009-03-22 11:13:06 -0500 (Sun, 22 Mar 2009)
New Revision: 10115

Modified:
   django/trunk/AUTHORS
   django/trunk/django/contrib/localflavor/generic/forms.py
   django/trunk/django/forms/fields.py
   django/trunk/django/forms/widgets.py
   django/trunk/docs/ref/contrib/localflavor.txt
   django/trunk/docs/ref/forms/fields.txt
   django/trunk/docs/ref/forms/widgets.txt
   django/trunk/tests/regressiontests/forms/widgets.py
Log:
Fixed #8962 -- Consistently support format and input_format in the various 
(individual, combined, split) date and time form fields and widgets.

Many thanks to Tai Lee for doing all the work here.


Modified: django/trunk/AUTHORS
===================================================================
--- django/trunk/AUTHORS        2009-03-22 07:58:29 UTC (rev 10114)
+++ django/trunk/AUTHORS        2009-03-22 16:13:06 UTC (rev 10115)
@@ -256,6 +256,7 @@
     Eugene Lazutkin <http://lazutkin.com/blog/>
     lcord...@point45.com
     Jeong-Min Lee <false...@gmail.com>
+    Tai Lee <real.hu...@mrmachine.net>
     Jannis Leidel <j...@websushi.org>
     Christopher Lenz <http://www.cmlenz.net/>
     lero...@gmail.com
@@ -295,7 +296,6 @@
     Aljosa Mohorovic <aljosa.mohoro...@gmail.com>
     Ramiro Morales <r...@gmx.net>
     Eric Moritz <http://eric.themoritzfamily.com/>
-    mrmachine <real.hu...@mrmachine.net>
     Robin Munn <http://www.geekforgod.com/>
     James Murty
     msundstr

Modified: django/trunk/django/contrib/localflavor/generic/forms.py
===================================================================
--- django/trunk/django/contrib/localflavor/generic/forms.py    2009-03-22 
07:58:29 UTC (rev 10114)
+++ django/trunk/django/contrib/localflavor/generic/forms.py    2009-03-22 
16:13:06 UTC (rev 10115)
@@ -36,3 +36,13 @@
     def __init__(self, input_formats=None, *args, **kwargs):
         input_formats = input_formats or DEFAULT_DATETIME_INPUT_FORMATS
         super(DateTimeField, self).__init__(input_formats=input_formats, 
*args, **kwargs)
+
+class SplitDateTimeField(forms.SplitDateTimeField):
+    """
+    Split date and time input fields which use non-US date and time input
+    formats by default.
+    """
+    def __init__(self, input_date_formats=None, input_time_formats=None, 
*args, **kwargs):
+        input_date_formats = input_date_formats or DEFAULT_DATE_INPUT_FORMATS
+        super(SplitDateTimeField, 
self).__init__(input_date_formats=input_date_formats,
+                                                 
input_time_formats=input_time_formats, *args, **kwargs)

Modified: django/trunk/django/forms/fields.py
===================================================================
--- django/trunk/django/forms/fields.py 2009-03-22 07:58:29 UTC (rev 10114)
+++ django/trunk/django/forms/fields.py 2009-03-22 16:13:06 UTC (rev 10115)
@@ -28,7 +28,7 @@
 from django.utils.encoding import smart_unicode, smart_str
 
 from util import ErrorList, ValidationError
-from widgets import TextInput, PasswordInput, HiddenInput, 
MultipleHiddenInput, FileInput, CheckboxInput, Select, NullBooleanSelect, 
SelectMultiple, DateTimeInput, TimeInput, SplitDateTimeWidget, 
SplitHiddenDateTimeWidget
+from widgets import TextInput, PasswordInput, HiddenInput, 
MultipleHiddenInput, FileInput, CheckboxInput, Select, NullBooleanSelect, 
SelectMultiple, DateInput, DateTimeInput, TimeInput, SplitDateTimeWidget, 
SplitHiddenDateTimeWidget
 from django.core.files.uploadedfile import SimpleUploadedFile as UploadedFile
 
 __all__ = (
@@ -283,6 +283,7 @@
 )
 
 class DateField(Field):
+    widget = DateInput 
     default_error_messages = {
         'invalid': _(u'Enter a valid date.'),
     }
@@ -850,13 +851,13 @@
         'invalid_time': _(u'Enter a valid time.'),
     }
 
-    def __init__(self, *args, **kwargs):
+    def __init__(self, input_date_formats=None, input_time_formats=None, 
*args, **kwargs):
         errors = self.default_error_messages.copy()
         if 'error_messages' in kwargs:
             errors.update(kwargs['error_messages'])
         fields = (
-            DateField(error_messages={'invalid': errors['invalid_date']}),
-            TimeField(error_messages={'invalid': errors['invalid_time']}),
+            DateField(input_formats=input_date_formats, 
error_messages={'invalid': errors['invalid_date']}),
+            TimeField(input_formats=input_time_formats, 
error_messages={'invalid': errors['invalid_time']}),
         )
         super(SplitDateTimeField, self).__init__(fields, *args, **kwargs)
 

Modified: django/trunk/django/forms/widgets.py
===================================================================
--- django/trunk/django/forms/widgets.py        2009-03-22 07:58:29 UTC (rev 
10114)
+++ django/trunk/django/forms/widgets.py        2009-03-22 16:13:06 UTC (rev 
10115)
@@ -23,7 +23,7 @@
 __all__ = (
     'Media', 'MediaDefiningClass', 'Widget', 'TextInput', 'PasswordInput',
     'HiddenInput', 'MultipleHiddenInput',
-    'FileInput', 'DateTimeInput', 'TimeInput', 'Textarea', 'CheckboxInput',
+    'FileInput', 'DateInput', 'DateTimeInput', 'TimeInput', 'Textarea', 
'CheckboxInput',
     'Select', 'NullBooleanSelect', 'SelectMultiple', 'RadioSelect',
     'CheckboxSelectMultiple', 'MultiWidget',
     'SplitDateTimeWidget',
@@ -285,6 +285,23 @@
         return mark_safe(u'<textarea%s>%s</textarea>' % (flatatt(final_attrs),
                 conditional_escape(force_unicode(value))))
 
+class DateInput(Input):
+    input_type = 'text'
+    format = '%Y-%m-%d'     # '2006-10-25'
+
+    def __init__(self, attrs=None, format=None):
+        super(DateInput, self).__init__(attrs)
+        if format:
+            self.format = format
+
+    def render(self, name, value, attrs=None):
+        if value is None:
+            value = ''
+        elif hasattr(value, 'strftime'):
+            value = datetime_safe.new_date(value)
+            value = value.strftime(self.format)
+        return super(DateInput, self).render(name, value, attrs)
+
 class DateTimeInput(Input):
     input_type = 'text'
     format = '%Y-%m-%d %H:%M:%S'     # '2006-10-25 14:30:59'
@@ -304,12 +321,18 @@
 
 class TimeInput(Input):
     input_type = 'text'
+    format = '%H:%M:%S'     # '14:30:59'
 
+    def __init__(self, attrs=None, format=None):
+        super(TimeInput, self).__init__(attrs)
+        if format:
+            self.format = format
+
     def render(self, name, value, attrs=None):
         if value is None:
             value = ''
-        elif isinstance(value, time):
-            value = value.replace(microsecond=0)
+        elif hasattr(value, 'strftime'):
+            value = value.strftime(self.format)
         return super(TimeInput, self).render(name, value, attrs)
 
 class CheckboxInput(Widget):
@@ -654,8 +677,16 @@
     """
     A Widget that splits datetime input into two <input type="text"> boxes.
     """
-    def __init__(self, attrs=None):
-        widgets = (TextInput(attrs=attrs), TextInput(attrs=attrs))
+    date_format = DateInput.format
+    time_format = TimeInput.format
+
+    def __init__(self, attrs=None, date_format=None, time_format=None):
+        if date_format:
+            self.date_format = date_format
+        if time_format:
+            self.time_format = time_format
+        widgets = (DateInput(attrs=attrs, format=self.date_format),
+                   TimeInput(attrs=attrs, format=self.time_format))
         super(SplitDateTimeWidget, self).__init__(widgets, attrs)
 
     def decompress(self, value):
@@ -670,4 +701,3 @@
     def __init__(self, attrs=None):
         widgets = (HiddenInput(attrs=attrs), HiddenInput(attrs=attrs))
         super(SplitDateTimeWidget, self).__init__(widgets, attrs)
-

Modified: django/trunk/docs/ref/contrib/localflavor.txt
===================================================================
--- django/trunk/docs/ref/contrib/localflavor.txt       2009-03-22 07:58:29 UTC 
(rev 10114)
+++ django/trunk/docs/ref/contrib/localflavor.txt       2009-03-22 16:13:06 UTC 
(rev 10115)
@@ -66,9 +66,9 @@
     * `United States of America`_
 
 The ``django.contrib.localflavor`` package also includes a ``generic`` 
subpackage,
-containing useful code that is not specific to one particular country or
-culture. Currently, it defines date and datetime input fields based on those
-from :ref:`forms <topics-forms-index>`, but with non-US default formats.
+containing useful code that is not specific to one particular country or 
culture.
+Currently, it defines date, datetime and split datetime input fields based on
+those from :ref:`forms <topics-forms-index>`, but with non-US default formats.
 Here's an example of how to use them::
 
     from django import forms

Modified: django/trunk/docs/ref/forms/fields.txt
===================================================================
--- django/trunk/docs/ref/forms/fields.txt      2009-03-22 07:58:29 UTC (rev 
10114)
+++ django/trunk/docs/ref/forms/fields.txt      2009-03-22 16:13:06 UTC (rev 
10115)
@@ -398,7 +398,7 @@
 
 .. class:: DateField(**kwargs)
 
-    * Default widget: ``TextInput``
+    * Default widget: ``DateInput``
     * Empty value: ``None``
     * Normalizes to: A Python ``datetime.date`` object.
     * Validates that the given value is either a ``datetime.date``,
@@ -420,6 +420,10 @@
     '%B %d %Y', '%B %d, %Y',            # 'October 25 2006', 'October 25, 2006'
     '%d %B %Y', '%d %B, %Y',            # '25 October 2006', '25 October, 2006'
 
+.. versionchanged:: 1.1
+   The ``DateField`` previously used a ``TextInput`` widget by default. It now
+   uses a ``DateInput`` widget.
+
 ``DateTimeField``
 ~~~~~~~~~~~~~~~~~
 
@@ -739,6 +743,36 @@
 
 .. class:: SplitDateTimeField(**kwargs)
 
+    * Default widget: ``SplitDateTimeWidget``
+    * Empty value: ``None``
+    * Normalizes to: A Python ``datetime.datetime`` object.
+    * Validates that the given value is a ``datetime.datetime`` or string
+      formatted in a particular datetime format.
+    * Error message keys: ``required``, ``invalid``
+
+Takes two optional arguments:
+
+.. attribute:: SplitDateTimeField.input_date_formats
+
+    A list of formats used to attempt to convert a string to a valid
+    ``datetime.date`` object.
+
+If no ``input_date_formats`` argument is provided, the default input formats
+for ``DateField`` are used.
+
+.. attribute:: SplitDateTimeField.input_time_formats
+
+    A list of formats used to attempt to convert a string to a valid
+    ``datetime.time`` object.
+
+If no ``input_time_formats`` argument is provided, the default input formats
+for ``TimeField`` are used.
+
+.. versionchanged:: 1.1
+   The ``SplitDateTimeField`` previously used two ``TextInput`` widgets by
+   default. The ``input_date_formats`` and ``input_time_formats`` arguments
+   are also new.
+
 Fields which handle relationships
 ---------------------------------
 

Modified: django/trunk/docs/ref/forms/widgets.txt
===================================================================
--- django/trunk/docs/ref/forms/widgets.txt     2009-03-22 07:58:29 UTC (rev 
10114)
+++ django/trunk/docs/ref/forms/widgets.txt     2009-03-22 16:13:06 UTC (rev 
10115)
@@ -36,12 +36,49 @@
 
     File upload input: ``<input type='file' ...>``
 
+.. class:: DateInput
+
+    .. versionadded:: 1.1
+
+    Date input as a simple text box: ``<input type='text' ...>``
+
+    Takes one optional argument:
+    
+    .. attribute:: DateInput.format
+
+        The format in which this field's initial value will be displayed.
+
+    If no ``format`` argument is provided, the default format is 
``'%Y-%m-%d'``.
+
 .. class:: DateTimeInput
 
     .. versionadded:: 1.0
 
     Date/time input as a simple text box: ``<input type='text' ...>``
 
+    Takes one optional argument:
+    
+    .. attribute:: DateTimeInput.format
+    
+        The format in which this field's initial value will be displayed.
+    
+    If no ``format`` argument is provided, the default format is ``'%Y-%m-%d 
%H:%M:%S'``.
+
+.. class:: TimeInput
+
+    Time input as a simple text box: ``<input type='text' ...>``
+
+    Takes one optional argument:
+    
+    .. attribute:: TimeInput.format
+    
+        The format in which this field's initial value will be displayed.
+    
+    If no ``format`` argument is provided, the default format is 
``'%H:%M:%S'``.
+
+    .. versionchanged:: 1.1
+       The ``format`` argument was not supported in Django 1.0.
+
 .. class:: Textarea
 
     Text area: ``<textarea>...</textarea>``
@@ -91,9 +128,16 @@
 
 .. class:: SplitDateTimeWidget
 
-    Wrapper around two ``TextInput`` widgets: one for the date, and one for the
-    time.
+    Wrapper around two widgets: ``DateInput`` for the date, and ``TimeInput``
+    for the time.
 
+    Takes two optional arguments, ``date_format`` and ``time_format``, which
+    work just like the ``format`` argument for ``DateInput`` and ``TimeInput``.
+    
+    .. versionchanged:: 1.1
+       The ``date_format`` and ``time_format`` arguments were not supported in 
Django 1.0.
+
+
 Specifying widgets
 ------------------
 

Modified: django/trunk/tests/regressiontests/forms/widgets.py
===================================================================
--- django/trunk/tests/regressiontests/forms/widgets.py 2009-03-22 07:58:29 UTC 
(rev 10114)
+++ django/trunk/tests/regressiontests/forms/widgets.py 2009-03-22 16:13:06 UTC 
(rev 10115)
@@ -1071,6 +1071,11 @@
 >>> w.render('date', datetime.datetime(2006, 1, 10, 7, 30))
 u'<input type="text" class="pretty" value="2006-01-10" name="date_0" /><input 
type="text" class="pretty" value="07:30:00" name="date_1" />'
 
+Use 'date_format' and 'time_format' to change the way a value is displayed.
+>>> w = SplitDateTimeWidget(date_format='%d/%m/%Y', time_format='%H:%M')
+>>> w.render('date', datetime.datetime(2006, 1, 10, 7, 30))
+u'<input type="text" name="date_0" value="10/01/2006" /><input type="text" 
name="date_1" value="07:30" />'
+
 >>> w._has_changed(datetime.datetime(2008, 5, 5, 12, 40, 00), [u'2008-05-05', 
 >>> u'12:40:00'])
 False
 >>> w._has_changed(datetime.datetime(2008, 5, 5, 12, 40, 00), [u'2008-05-05', 
 >>> u'12:41:00'])
@@ -1093,6 +1098,34 @@
 >>> w.render('date', datetime.datetime(2007, 9, 17, 12, 51))
 u'<input type="text" name="date" value="2007-09-17 12:51:00" />'
 
+Use 'format' to change the way a value is displayed.
+>>> w = DateTimeInput(format='%d/%m/%Y %H:%M')
+>>> w.render('date', d)
+u'<input type="text" name="date" value="17/09/2007 12:51" />'
+
+# DateInput ###################################################################
+
+>>> w = DateInput()
+>>> w.render('date', None)
+u'<input type="text" name="date" />'
+>>> d = datetime.date(2007, 9, 17)
+>>> print d
+2007-09-17
+
+>>> w.render('date', d)
+u'<input type="text" name="date" value="2007-09-17" />'
+>>> w.render('date', datetime.date(2007, 9, 17))
+u'<input type="text" name="date" value="2007-09-17" />'
+
+We should be able to initialize from a unicode value.
+>>> w.render('date', u'2007-09-17')
+u'<input type="text" name="date" value="2007-09-17" />'
+
+Use 'format' to change the way a value is displayed.
+>>> w = DateInput(format='%d/%m/%Y')
+>>> w.render('date', d)
+u'<input type="text" name="date" value="17/09/2007" />'
+
 # TimeInput ###################################################################
 
 >>> w = TimeInput()
@@ -1114,6 +1147,11 @@
 >>> w.render('time', u'13:12:11')
 u'<input type="text" name="time" value="13:12:11" />'
 
+Use 'format' to change the way a value is displayed.
+>>> w = TimeInput(format='%H:%M')
+>>> w.render('time', t)
+u'<input type="text" name="time" value="12:51" />'
+
 # SplitHiddenDateTimeWidget ###################################################
 
 >>> from django.forms.widgets import SplitHiddenDateTimeWidget
@@ -1121,6 +1159,9 @@
 >>> w = SplitHiddenDateTimeWidget()
 >>> w.render('date', '')
 u'<input type="hidden" name="date_0" /><input type="hidden" name="date_1" />'
+>>> d = datetime.datetime(2007, 9, 17, 12, 51, 34, 482548)
+>>> print d
+2007-09-17 12:51:34.482548
 >>> w.render('date', d)
 u'<input type="hidden" name="date_0" value="2007-09-17" /><input type="hidden" 
name="date_1" value="12:51:34" />'
 >>> w.render('date', datetime.datetime(2007, 9, 17, 12, 51, 34))


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to django-updates@googlegroups.com
To unsubscribe from this group, send email to 
django-updates+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to