Ticket #8962: datetime-formatting-r8983.diff

File datetime-formatting-r8983.diff, 13.8 KB (added by Tai Lee, 16 years ago)
  • django/forms/fields.py

     
    2828from django.utils.encoding import smart_unicode, smart_str
    2929
    3030from util import ErrorList, ValidationError
    31 from widgets import TextInput, PasswordInput, HiddenInput, MultipleHiddenInput, FileInput, CheckboxInput, Select, NullBooleanSelect, SelectMultiple, DateTimeInput, TimeInput, SplitHiddenDateTimeWidget
     31from widgets import TextInput, PasswordInput, HiddenInput, MultipleHiddenInput, FileInput, CheckboxInput, Select, NullBooleanSelect, SelectMultiple, DateInput, DateTimeInput, TimeInput, SplitDateTimeWidget, SplitHiddenDateTimeWidget
    3232from django.core.files.uploadedfile import SimpleUploadedFile as UploadedFile
    3333
    3434__all__ = (
     
    283283)
    284284
    285285class DateField(Field):
     286    widget = DateInput
    286287    default_error_messages = {
    287288        'invalid': _(u'Enter a valid date.'),
    288289    }
     
    843844        self.widget.choices = self.choices
    844845
    845846class SplitDateTimeField(MultiValueField):
     847    widget = SplitDateTimeWidget
    846848    hidden_widget = SplitHiddenDateTimeWidget
    847849    default_error_messages = {
    848850        'invalid_date': _(u'Enter a valid date.'),
    849851        'invalid_time': _(u'Enter a valid time.'),
    850852    }
    851853
    852     def __init__(self, *args, **kwargs):
     854    def __init__(self, input_date_formats=None, input_time_formats=None, *args, **kwargs):
    853855        errors = self.default_error_messages.copy()
    854856        if 'error_messages' in kwargs:
    855857            errors.update(kwargs['error_messages'])
    856858        fields = (
    857             DateField(error_messages={'invalid': errors['invalid_date']}),
    858             TimeField(error_messages={'invalid': errors['invalid_time']}),
     859            DateField(input_formats=input_date_formats, error_messages={'invalid': errors['invalid_date']}),
     860            TimeField(input_formats=input_time_formats, error_messages={'invalid': errors['invalid_time']}),
    859861        )
    860862        super(SplitDateTimeField, self).__init__(fields, *args, **kwargs)
    861863
  • django/forms/widgets.py

     
    2323__all__ = (
    2424    'Media', 'MediaDefiningClass', 'Widget', 'TextInput', 'PasswordInput',
    2525    'HiddenInput', 'MultipleHiddenInput',
    26     'FileInput', 'DateTimeInput', 'TimeInput', 'Textarea', 'CheckboxInput',
     26    'FileInput', 'DateInput', 'DateTimeInput', 'TimeInput', 'Textarea', 'CheckboxInput',
    2727    'Select', 'NullBooleanSelect', 'SelectMultiple', 'RadioSelect',
    2828    'CheckboxSelectMultiple', 'MultiWidget',
    2929    'SplitDateTimeWidget',
     
    286286        return mark_safe(u'<textarea%s>%s</textarea>' % (flatatt(final_attrs),
    287287                conditional_escape(force_unicode(value))))
    288288
     289class DateInput(Input):
     290    input_type = 'text'
     291    format = '%Y-%m-%d'     # '2006-10-25'
     292
     293    def __init__(self, attrs=None, format=None):
     294        super(DateInput, self).__init__(attrs)
     295        if format:
     296            self.format = format
     297
     298    def render(self, name, value, attrs=None):
     299        if value is None:
     300            value = ''
     301        elif hasattr(value, 'strftime'):
     302            value = datetime_safe.new_date(value)
     303            value = value.strftime(self.format)
     304        return super(DateInput, self).render(name, value, attrs)
     305
    289306class DateTimeInput(Input):
    290307    input_type = 'text'
    291308    format = '%Y-%m-%d %H:%M:%S'     # '2006-10-25 14:30:59'
     
    305322
    306323class TimeInput(Input):
    307324    input_type = 'text'
     325    format = '%H:%M:%S'     # '14:30:59'
    308326
     327    def __init__(self, attrs=None, format=None):
     328        super(TimeInput, self).__init__(attrs)
     329        if format:
     330            self.format = format
     331
    309332    def render(self, name, value, attrs=None):
    310333        if value is None:
    311334            value = ''
    312         elif isinstance(value, time):
    313             value = value.replace(microsecond=0)
     335        elif hasattr(value, 'strftime'):
     336            value = value.strftime(self.format)
    314337        return super(TimeInput, self).render(name, value, attrs)
    315338
    316339class CheckboxInput(Widget):
     
    655678    """
    656679    A Widget that splits datetime input into two <input type="text"> boxes.
    657680    """
    658     def __init__(self, attrs=None):
    659         widgets = (TextInput(attrs=attrs), TextInput(attrs=attrs))
     681    def __init__(self, attrs=None, date_format=None, time_format=None):
     682        widgets = (DateInput(attrs=attrs, format=date_format),
     683                   TimeInput(attrs=attrs, format=time_format))
    660684        super(SplitDateTimeWidget, self).__init__(widgets, attrs)
    661685
    662686    def decompress(self, value):
     
    671695    def __init__(self, attrs=None):
    672696        widgets = (HiddenInput(attrs=attrs), HiddenInput(attrs=attrs))
    673697        super(SplitDateTimeWidget, self).__init__(widgets, attrs)
    674 
  • django/contrib/localflavor/generic/forms.py

     
    3636    def __init__(self, input_formats=None, *args, **kwargs):
    3737        input_formats = input_formats or DEFAULT_DATETIME_INPUT_FORMATS
    3838        super(DateTimeField, self).__init__(input_formats=input_formats, *args, **kwargs)
     39
     40class SplitDateTimeField(forms.SplitDateTimeField):
     41    """
     42    Split date and time input fields which use non-US date and time input
     43    formats by default.
     44    """
     45    def __init__(self, input_date_formats=None, input_time_formats=None, *args, **kwargs):
     46        input_date_formats = input_date_formats or DEFAULT_DATE_INPUT_FORMATS
     47        input_time_formats = input_time_formats
     48        super(SplitDateTimeField, self).__init__(input_date_formats=input_date_formats,
     49                                                 input_time_formats=input_time_formats, *args, **kwargs)
  • tests/regressiontests/forms/widgets.py

     
    10711071>>> w.render('date', datetime.datetime(2006, 1, 10, 7, 30))
    10721072u'<input type="text" class="pretty" value="2006-01-10" name="date_0" /><input type="text" class="pretty" value="07:30:00" name="date_1" />'
    10731073
     1074Or use 'date_format' and 'time_format' to change the way a value is displayed.
     1075>>> w = SplitDateTimeWidget(date_format='%d/%m/%Y', time_format='%H:%M')
     1076>>> w.render('date', datetime.datetime(2006, 1, 10, 7, 30))
     1077u'<input type="text" name="date_0" value="10/01/2006" /><input type="text" name="date_1" value="07:30" />'
     1078
    10741079>>> w._has_changed(datetime.datetime(2008, 5, 5, 12, 40, 00), [u'2008-05-05', u'12:40:00'])
    10751080False
    10761081>>> w._has_changed(datetime.datetime(2008, 5, 5, 12, 40, 00), [u'2008-05-05', u'12:41:00'])
     
    10931098>>> w.render('date', datetime.datetime(2007, 9, 17, 12, 51))
    10941099u'<input type="text" name="date" value="2007-09-17 12:51:00" />'
    10951100
     1101Or use 'format' to change the way a value is displayed.
     1102>>> w = DateTimeInput(format='%d/%m/%Y %H:%M')
     1103>>> w.render('date', d)
     1104u'<input type="text" name="date" value="17/09/2007 12:51" />'
     1105
     1106# DateInput ###################################################################
     1107
     1108>>> w = DateInput()
     1109>>> w.render('date', None)
     1110u'<input type="text" name="date" />'
     1111>>> d = datetime.date(2007, 9, 17)
     1112>>> print d
     11132007-09-17
     1114
     1115>>> w.render('date', d)
     1116u'<input type="text" name="date" value="2007-09-17" />'
     1117>>> w.render('date', datetime.date(2007, 9, 17))
     1118u'<input type="text" name="date" value="2007-09-17" />'
     1119
     1120We should be able to initialize from a unicode value.
     1121>>> w.render('date', u'2007-09-17')
     1122u'<input type="text" name="date" value="2007-09-17" />'
     1123
     1124Or use 'format' to change the way a value is displayed.
     1125>>> w = DateInput(format='%d/%m/%Y')
     1126>>> w.render('date', d)
     1127u'<input type="text" name="date" value="17/09/2007" />'
     1128
    10961129# TimeInput ###################################################################
    10971130
    10981131>>> w = TimeInput()
     
    11141147>>> w.render('time', u'13:12:11')
    11151148u'<input type="text" name="time" value="13:12:11" />'
    11161149
     1150Or use 'format' to change the way a value is displayed.
     1151>>> w = TimeInput(format='%H:%M')
     1152>>> w.render('time', t)
     1153u'<input type="text" name="time" value="12:51" />'
     1154
    11171155# SplitHiddenDateTimeWidget ###################################################
    11181156
    11191157>>> from django.forms.widgets import SplitHiddenDateTimeWidget
     
    11211159>>> w = SplitHiddenDateTimeWidget()
    11221160>>> w.render('date', '')
    11231161u'<input type="hidden" name="date_0" /><input type="hidden" name="date_1" />'
     1162>>> d = datetime.datetime(2007, 9, 17, 12, 51, 34, 482548)
     1163>>> print d
     11642007-09-17 12:51:34.482548
     1165
    11241166>>> w.render('date', d)
    11251167u'<input type="hidden" name="date_0" value="2007-09-17" /><input type="hidden" name="date_1" value="12:51:34" />'
    11261168>>> w.render('date', datetime.datetime(2007, 9, 17, 12, 51, 34))
  • docs/ref/contrib/localflavor.txt

     
    6565    * `United States of America`_
    6666
    6767The ``django.contrib.localflavor`` package also includes a ``generic`` subpackage,
    68 containing useful code that is not specific to one particular country or
    69 culture. Currently, it defines date and datetime input fields based on those
    70 from :ref:`forms <topics-forms-index>`, but with non-US default formats.
     68containing useful code that is not specific to one particular country or culture.
     69Currently, it defines date, datetime and split datetime input fields based on
     70those from :ref:`forms <topics-forms-index>`, but with non-US default formats.
    7171Here's an example of how to use them::
    7272
    7373    from django import forms
  • docs/ref/forms/fields.txt

     
    396396
    397397.. class:: DateField(**kwargs)
    398398
    399     * Default widget: ``TextInput``
     399    * Default widget: ``DateInput``
    400400    * Empty value: ``None``
    401401    * Normalizes to: A Python ``datetime.date`` object.
    402402    * Validates that the given value is either a ``datetime.date``,
     
    418418    '%B %d %Y', '%B %d, %Y',            # 'October 25 2006', 'October 25, 2006'
    419419    '%d %B %Y', '%d %B, %Y',            # '25 October 2006', '25 October, 2006'
    420420
     421.. versionchanged:: development version
     422   The ``DateField`` used to use a ``TextInput`` widget by default. This has now changed.
     423
    421424``DateTimeField``
    422425~~~~~~~~~~~~~~~~~
    423426
     
    737740
    738741.. class:: SplitDateTimeField(**kwargs)
    739742
     743    * Default widget: ``SplitDateTimeWidget``
     744    * Empty value: ``None``
     745    * Normalizes to: A Python ``datetime.datetime`` object.
     746    * Validates that the given value is either a ``datetime.datetime``,
     747      ``datetime.date`` or string formatted in a particular datetime format.
     748    * Error message keys: ``required``, ``invalid``
     749
     750Takes two optional arguments:
     751
     752.. attribute:: SplitDateTimeField.input_date_formats
     753
     754A list of formats used to attempt to convert a string to a valid
     755``datetime.date`` object.
     756
     757If no ``input_date_formats`` argument is provided, the default input formats
     758for ``DateField`` are used.
     759
     760.. attribute:: SplitDateTimeField.input_time_formats
     761
     762A list of formats used to attempt to convert a string to a valid
     763``datetime.time`` object.
     764
     765If no ``input_time_formats`` argument is provided, the default input formats
     766for ``TimeField`` are used.
     767
     768.. versionchanged:: development version
     769   The ``SplitDateTimeField`` used to use two ``TextInput`` widgets by default.
     770   The ``input_date_formats`` and ``input_time_formats`` arguments are also
     771   new in the development version.
     772
    740773Fields which handle relationships
    741774---------------------------------
    742775
  • docs/ref/forms/widgets.txt

     
    3636
    3737    File upload input: ``<input type='file' ...>``
    3838
     39.. class:: DateInput
     40
     41    .. versionadded:: development version
     42
     43    Date input as a simple text box: ``<input type='text' ...>``
     44
     45    Takes one optional argument:
     46   
     47    .. attribute:: DateInput.format
     48
     49        The format in which this field's initial value will be displayed.
     50
     51    If no ``format`` argument is provided, the default format is ``'%Y-%m-%d'``.
     52
    3953.. class:: DateTimeInput
    4054
    4155    .. versionadded:: 1.0
    4256
    4357    Date/time input as a simple text box: ``<input type='text' ...>``
    4458
     59    Takes one optional argument:
     60   
     61    .. attribute:: DateTimeInput.format
     62   
     63        The format in which this field's initial value will be displayed.
     64   
     65    If no ``format`` argument is provided, the default format is ``'%Y-%m-%d %H:%M:%S'``.
     66
     67.. class:: TimeInput
     68
     69    Time input as a simple text box: ``<input type='text' ...>``
     70
     71    Takes one optional argument:
     72   
     73    .. attribute:: TimeInput.format
     74   
     75        The format in which this field's initial value will be displayed.
     76   
     77    If no ``format`` argument is provided, the default format is ``'%H:%M:%S'``.
     78
     79    .. versionchanged:: development version
     80       The ``format`` argument is new in the development version.
     81
    4582.. class:: Textarea
    4683
    4784    Text area: ``<textarea>...</textarea>``
     
    91128
    92129.. class:: SplitDateTimeWidget
    93130
    94     Wrapper around two ``TextInput`` widgets: one for the date, and one for the
    95     time.
     131    Wrapper around two widgets: ``DateInput`` for the date, and ``TimeInput``
     132    for the time.
    96133
     134    Takes two optional arguments, ``date_format`` and ``time_format``, which
     135    work just like the ``format`` argument for ``DateInput`` and ``TimeInput``.
     136
    97137Specifying widgets
    98138------------------
    99139
Back to Top