=== django/newforms/forms.py
==================================================================
|
|
|
189 | 189 | for name, field in self.fields.items(): |
190 | 190 | if name in exceptions: |
191 | 191 | continue |
192 | | # value_from_datadict() gets the data from the dictionary. |
| 192 | # value_from_datadict() gets the data from the data dictionaries. |
193 | 193 | # Each widget type knows how to retrieve its own data, because some |
194 | 194 | # widgets split data over several HTML fields. |
195 | 195 | value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name)) |
196 | | # HACK: ['', ''] and [None, None] deal with SplitDateTimeWidget. This should be more robust. |
197 | | if value not in (None, '', ['', ''], [None, None]): |
| 196 | if not field.widget.is_empty(value): |
198 | 197 | return False |
199 | 198 | return True |
200 | 199 | |
=== django/newforms/widgets.py
==================================================================
|
|
|
164 | 164 | of this widget. Returns None if it's not provided. |
165 | 165 | """ |
166 | 166 | return data.get(name, None) |
| 167 | |
| 168 | def is_empty(self, value): |
| 169 | """ |
| 170 | Given a dictionary of data and this widget's name, return True if the |
| 171 | widget data is empty or False when not empty. |
| 172 | """ |
| 173 | if value not in (None, ''): |
| 174 | return False |
| 175 | return True |
167 | 176 | |
168 | 177 | def id_for_label(self, id_): |
169 | 178 | """ |
… |
… |
|
294 | 303 | # send results for unselected checkboxes. |
295 | 304 | return False |
296 | 305 | return super(CheckboxInput, self).value_from_datadict(data, files, name) |
| 306 | |
| 307 | def is_empty(self, value): |
| 308 | # this widget will always either be True or False, so always return the |
| 309 | # opposite value so False values will make the form empty |
| 310 | return not value |
297 | 311 | |
298 | 312 | class Select(Widget): |
299 | 313 | def __init__(self, attrs=None, choices=()): |
… |
… |
|
333 | 347 | def value_from_datadict(self, data, files, name): |
334 | 348 | value = data.get(name, None) |
335 | 349 | return {u'2': True, u'3': False, True: True, False: False}.get(value, None) |
| 350 | |
| 351 | def is_empty(self, value): |
| 352 | # this widget will always either be True, False or None, so always |
| 353 | # return the opposite value so False and None values will make the |
| 354 | # form empty. |
| 355 | return not value |
336 | 356 | |
337 | 357 | class SelectMultiple(Widget): |
338 | 358 | def __init__(self, attrs=None, choices=()): |
… |
… |
|
521 | 541 | |
522 | 542 | def value_from_datadict(self, data, files, name): |
523 | 543 | return [widget.value_from_datadict(data, files, name + '_%s' % i) for i, widget in enumerate(self.widgets)] |
| 544 | |
| 545 | def is_empty(self, value): |
| 546 | for widget, val in zip(self.widgets, value): |
| 547 | if not widget.is_empty(val): |
| 548 | return False |
| 549 | return True |
524 | 550 | |
525 | 551 | def format_output(self, rendered_widgets): |
526 | 552 | """ |
=== tests/regressiontests/forms/widgets.py
==================================================================
|
|
|
282 | 282 | >>> w.value_from_datadict({}, {}, 'testing') |
283 | 283 | False |
284 | 284 | |
| 285 | The CheckboxInput widget will always be empty when there is a False value |
| 286 | >>> w.is_empty(False) |
| 287 | True |
| 288 | >>> w.is_empty(True) |
| 289 | False |
| 290 | |
285 | 291 | # Select Widget ############################################################### |
286 | 292 | |
287 | 293 | >>> w = Select() |
… |
… |
|
432 | 438 | <option value="3" selected="selected">No</option> |
433 | 439 | </select> |
434 | 440 | |
| 441 | The NullBooleanSelect widget will always be empty when Unknown or No is selected |
| 442 | as its value. This is to stay compliant with the CheckboxInput behavior |
| 443 | >>> w.is_empty(False) |
| 444 | True |
| 445 | >>> w.is_empty(None) |
| 446 | True |
| 447 | >>> w.is_empty(True) |
| 448 | False |
| 449 | |
435 | 450 | """ + \ |
436 | 451 | r""" # [This concatenation is to keep the string below the jython's 32K limit]. |
437 | 452 | # SelectMultiple Widget ####################################################### |
… |
… |
|
834 | 849 | >>> w.render('name', ['john', 'lennon']) |
835 | 850 | u'<input id="bar_0" type="text" class="big" value="john" name="name_0" /><br /><input id="bar_1" type="text" class="small" value="lennon" name="name_1" />' |
836 | 851 | |
| 852 | The MultiWidget will be empty only when all widgets are considered empty. |
| 853 | >>> w.is_empty(['john', 'lennon']) |
| 854 | False |
| 855 | >>> w.is_empty(['john', '']) |
| 856 | False |
| 857 | >>> w.is_empty(['', '']) |
| 858 | True |
| 859 | >>> w.is_empty([None, None]) |
| 860 | True |
| 861 | |
837 | 862 | # SplitDateTimeWidget ######################################################### |
838 | 863 | |
839 | 864 | >>> w = SplitDateTimeWidget() |