Index: django/forms/fields.py
===================================================================
--- django/forms/fields.py (revision 8714)
+++ django/forms/fields.py (working copy)
@@ -27,7 +27,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
+from widgets import TextInput, PasswordInput, HiddenInput, MultipleHiddenInput, FileInput, CheckboxInput, Select, NullBooleanSelect, SelectMultiple, DateTimeInput, TimeInput, HiddenSplitDateTimeWidget
from django.core.files.uploadedfile import SimpleUploadedFile as UploadedFile
__all__ = (
@@ -811,6 +811,7 @@
self.widget.choices = self.choices
class SplitDateTimeField(MultiValueField):
+ hidden_widget = HiddenSplitDateTimeWidget
default_error_messages = {
'invalid_date': _(u'Enter a valid date.'),
'invalid_time': _(u'Enter a valid time.'),
Index: django/forms/widgets.py
===================================================================
--- django/forms/widgets.py (revision 8714)
+++ django/forms/widgets.py (working copy)
@@ -255,6 +255,61 @@
return data.getlist(name)
return data.get(name, None)
+class SplitHiddenInput(HiddenInput):
+ """
+ A widget that handles for fields that are split into
+ multiple values. Meant to be a hidden replacement for MultiWidget.
+ """
+ def __init__(self, widgets, attrs=None):
+ self.widgets = [isinstance(w, type) and w() or w for w in widgets]
+ super(SplitHiddenInput, self).__init__(attrs)
+
+ def render(self, name, value, attrs=None):
+ # value is a list of values, each corresponding to a widget
+ # in self.widgets.
+ if not isinstance(value, list):
+ value = self.decompress(value)
+ output = []
+ final_attrs = self.build_attrs(attrs, type=self.input_type)
+ id_ = final_attrs.get('id', None)
+ for i, widget in enumerate(self.widgets):
+ try:
+ widget_value = value[i]
+ except IndexError:
+ widget_value = None
+ if id_:
+ final_attrs = dict(final_attrs, id='%s_%s' % (id_, i))
+ output.append(widget.render(name + '_%s' % i, widget_value, final_attrs))
+ return mark_safe(self.format_output(output))
+
+ def id_for_label(self, id_):
+ # See the comment for RadioSelect.id_for_label()
+ if id_:
+ id_ += '_0'
+ return id_
+ id_for_label = classmethod(id_for_label)
+
+ def value_from_datadict(self, data, files, name):
+ return [widget.value_from_datadict(data, files, name + '_%s' % i) for i, widget in enumerate(self.widgets)]
+
+ def format_output(self, rendered_widgets):
+ """
+ Given a list of rendered widgets (as strings), returns a Unicode string
+ representing the HTML for the whole lot.
+
+ This hook allows you to format the HTML design of the widgets, if
+ needed.
+ """
+ return u''.join(rendered_widgets)
+
+ def decompress(self, value):
+ """
+ Returns a list of decompressed values for the given compressed value.
+ The given value can be assumed to be valid, but not necessarily
+ non-empty.
+ """
+ raise NotImplementedError('Subclasses must implement this method.')
+
class FileInput(Input):
input_type = 'file'
needs_multipart_form = True
@@ -662,3 +717,15 @@
return [value.date(), value.time().replace(microsecond=0)]
return [None, None]
+class HiddenSplitDateTimeWidget(SplitHiddenInput):
+ """
+ A Widget that splits datetime input into two boxes.
+ """
+ def __init__(self, attrs=None):
+ widgets = (HiddenInput(attrs=attrs), HiddenInput(attrs=attrs))
+ super(HiddenSplitDateTimeWidget, self).__init__(widgets, attrs)
+
+ def decompress(self, value):
+ if value:
+ return [value.date(), value.time().replace(microsecond=0)]
+ return [None, None]