| | 258 | class SplitHiddenInput(HiddenInput): |
| | 259 | """ |
| | 260 | A widget that handles <input type="hidden"> for fields that are split into |
| | 261 | multiple values. Meant to be a hidden replacement for MultiWidget. |
| | 262 | """ |
| | 263 | def __init__(self, widgets, attrs=None): |
| | 264 | self.widgets = [isinstance(w, type) and w() or w for w in widgets] |
| | 265 | super(SplitHiddenInput, self).__init__(attrs) |
| | 266 | |
| | 267 | def render(self, name, value, attrs=None): |
| | 268 | # value is a list of values, each corresponding to a widget |
| | 269 | # in self.widgets. |
| | 270 | if not isinstance(value, list): |
| | 271 | value = self.decompress(value) |
| | 272 | output = [] |
| | 273 | final_attrs = self.build_attrs(attrs, type=self.input_type) |
| | 274 | id_ = final_attrs.get('id', None) |
| | 275 | for i, widget in enumerate(self.widgets): |
| | 276 | try: |
| | 277 | widget_value = value[i] |
| | 278 | except IndexError: |
| | 279 | widget_value = None |
| | 280 | if id_: |
| | 281 | final_attrs = dict(final_attrs, id='%s_%s' % (id_, i)) |
| | 282 | output.append(widget.render(name + '_%s' % i, widget_value, final_attrs)) |
| | 283 | return mark_safe(self.format_output(output)) |
| | 284 | |
| | 285 | def id_for_label(self, id_): |
| | 286 | # See the comment for RadioSelect.id_for_label() |
| | 287 | if id_: |
| | 288 | id_ += '_0' |
| | 289 | return id_ |
| | 290 | id_for_label = classmethod(id_for_label) |
| | 291 | |
| | 292 | def value_from_datadict(self, data, files, name): |
| | 293 | return [widget.value_from_datadict(data, files, name + '_%s' % i) for i, widget in enumerate(self.widgets)] |
| | 294 | |
| | 295 | def format_output(self, rendered_widgets): |
| | 296 | """ |
| | 297 | Given a list of rendered widgets (as strings), returns a Unicode string |
| | 298 | representing the HTML for the whole lot. |
| | 299 | |
| | 300 | This hook allows you to format the HTML design of the widgets, if |
| | 301 | needed. |
| | 302 | """ |
| | 303 | return u''.join(rendered_widgets) |
| | 304 | |
| | 305 | def decompress(self, value): |
| | 306 | """ |
| | 307 | Returns a list of decompressed values for the given compressed value. |
| | 308 | The given value can be assumed to be valid, but not necessarily |
| | 309 | non-empty. |
| | 310 | """ |
| | 311 | raise NotImplementedError('Subclasses must implement this method.') |
| | 312 | |
| | 720 | class HiddenSplitDateTimeWidget(SplitHiddenInput): |
| | 721 | """ |
| | 722 | A Widget that splits datetime input into two <input type="text"> boxes. |
| | 723 | """ |
| | 724 | def __init__(self, attrs=None): |
| | 725 | widgets = (HiddenInput(attrs=attrs), HiddenInput(attrs=attrs)) |
| | 726 | super(HiddenSplitDateTimeWidget, self).__init__(widgets, attrs) |
| | 727 | |
| | 728 | def decompress(self, value): |
| | 729 | if value: |
| | 730 | return [value.date(), value.time().replace(microsecond=0)] |
| | 731 | return [None, None] |