Ticket #8962: 8962-datetime-format-r8983.2.diff

File 8962-datetime-format-r8983.2.diff, 14.6 KB (added by mrmachine, 7 years ago)

Set default date/time format for SplitDateTimeWidget as class attribute, so it can be overridden in a subclass.

  • 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    date_format = DateInput.format
     682    time_format = TimeInput.format
     683
     684    def __init__(self, attrs=None, date_format=None, time_format=None):
     685        if date_format:
     686            self.date_format = date_format
     687        if time_format:
     688            self.time_format = time_format
     689        widgets = (DateInput(attrs=attrs, format=self.date_format),
     690                   TimeInput(attrs=attrs, format=self.time_format))
    660691        super(SplitDateTimeWidget, self).__init__(widgets, attrs)
    661692
    662693    def decompress(self, value):
     
    671702    def __init__(self, attrs=None):
    672703        widgets = (HiddenInput(attrs=attrs), HiddenInput(attrs=attrs))
    673704        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        super(SplitDateTimeField, self).__init__(input_date_formats=input_date_formats,
     48                                                 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
     1074Use '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
     1101Use '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
     1124Use '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
     1150Use '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
    11241165>>> w.render('date', d)
    11251166u'<input type="hidden" name="date_0" value="2007-09-17" /><input type="hidden" name="date_1" value="12:51:34" />'
    11261167>>> w.render('date', datetime.datetime(2007, 9, 17, 12, 51, 34))
  • AUTHORS

     
    239239    Eugene Lazutkin <http://lazutkin.com/blog/>
    240240    lcordier@point45.com
    241241    Jeong-Min Lee <falsetru@gmail.com>
     242    Tai Lee <real.human@mrmachine.net>
    242243    Jannis Leidel <jl@websushi.org>
    243244    Christopher Lenz <http://www.cmlenz.net/>
    244245    lerouxb@gmail.com
     
    278279    Aljosa Mohorovic <aljosa.mohorovic@gmail.com>
    279280    Ramiro Morales <rm0@gmx.net>
    280281    Eric Moritz <http://eric.themoritzfamily.com/>
    281     mrmachine <real.human@mrmachine.net>
    282282    Robin Munn <http://www.geekforgod.com/>
    283283    James Murty
    284284    msundstr
  • 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`` previously used a ``TextInput`` widget by default. It now
     423   uses a ``DateInput`` widget.
     424
    421425``DateTimeField``
    422426~~~~~~~~~~~~~~~~~
    423427
     
    737741
    738742.. class:: SplitDateTimeField(**kwargs)
    739743
     744    * Default widget: ``SplitDateTimeWidget``
     745    * Empty value: ``None``
     746    * Normalizes to: A Python ``datetime.datetime`` object.
     747    * Validates that the given value is a ``datetime.datetime`` or string
     748      formatted in a particular datetime format.
     749    * Error message keys: ``required``, ``invalid``
     750
     751Takes two optional arguments:
     752
     753.. attribute:: SplitDateTimeField.input_date_formats
     754
     755    A list of formats used to attempt to convert a string to a valid
     756    ``datetime.date`` object.
     757
     758If no ``input_date_formats`` argument is provided, the default input formats
     759for ``DateField`` are used.
     760
     761.. attribute:: SplitDateTimeField.input_time_formats
     762
     763    A list of formats used to attempt to convert a string to a valid
     764    ``datetime.time`` object.
     765
     766If no ``input_time_formats`` argument is provided, the default input formats
     767for ``TimeField`` are used.
     768
     769.. versionchanged:: development version
     770   The ``SplitDateTimeField`` previously used two ``TextInput`` widgets by
     771   default. The ``input_date_formats`` and ``input_time_formats`` arguments
     772   are also new in the development version.
     773
    740774Fields which handle relationships
    741775---------------------------------
    742776
  • 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