Django

Code

Changeset 4148

Show
Ignore:
Timestamp:
11/30/06 16:06:08 (2 years ago)
Author:
adrian
Message:

newforms: Added check_test argument to CheckboxInput? and changed its render() behavior slightly. Also changed CheckboxSelectMultiple? to use checkboxes with the same name, rather than checkboxes with separate names

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/trunk/django/newforms/widgets.py

    r4146 r4148  
    9292 
    9393class CheckboxInput(Widget): 
     94    def __init__(self, attrs=None, check_test=bool): 
     95        # check_test is a callable that takes a value and returns True 
     96        # if the checkbox should be checked for that value. 
     97        self.attrs = attrs or {} 
     98        self.check_test = check_test 
     99 
    94100    def render(self, name, value, attrs=None): 
    95101        final_attrs = self.build_attrs(attrs, type='checkbox', name=name) 
    96         if value: final_attrs['checked'] = 'checked' 
     102        try: 
     103            result = self.check_test(value) 
     104        except: # Silently catch exceptions 
     105            result = False 
     106        if result: 
     107            final_attrs['checked'] = 'checked' 
     108        if value not in ('', True, False, None): 
     109            final_attrs['value'] = smart_unicode(value) # Only add the 'value' attribute if a value is non-empty. 
    97110        return u'<input%s />' % flatatt(final_attrs) 
    98111 
     
    194207        output = [u'<ul>'] 
    195208        str_values = set([smart_unicode(v) for v in value]) # Normalize to strings. 
    196         cb = CheckboxInput(final_attrs
     209        cb = CheckboxInput(final_attrs, check_test=lambda value: value in str_values
    197210        for option_value, option_label in chain(self.choices, choices): 
    198211            option_value = smart_unicode(option_value) 
    199             field_name = name + option_value 
    200             rendered_cb = cb.render(field_name, (option_value in str_values)) 
     212            rendered_cb = cb.render(name, option_value) 
    201213            output.append(u'<li><label>%s %s</label></li>' % (rendered_cb, escape(smart_unicode(option_label)))) 
    202214        output.append(u'</ul>') 
    203215        return u'\n'.join(output) 
    204  
    205     def value_from_datadict(self, data, name): 
    206         data_list = [k for k, v in self.choices if data.get(name + k)] 
    207         return data_list or None 
    208216 
    209217    def id_for_label(self, id_): 
  • django/trunk/tests/regressiontests/forms/tests.py

    r4147 r4148  
    165165>>> w.render('is_cool', '') 
    166166u'<input type="checkbox" name="is_cool" />' 
     167>>> w.render('is_cool', None) 
     168u'<input type="checkbox" name="is_cool" />' 
    167169>>> w.render('is_cool', False) 
    168170u'<input type="checkbox" name="is_cool" />' 
    169171>>> w.render('is_cool', True) 
    170172u'<input checked="checked" type="checkbox" name="is_cool" />' 
     173 
     174Using any value that's not in ('', None, False, True) will check the checkbox 
     175and set the 'value' attribute. 
     176>>> w.render('is_cool', 'foo') 
     177u'<input checked="checked" type="checkbox" name="is_cool" value="foo" />' 
     178 
    171179>>> w.render('is_cool', False, attrs={'class': 'pretty'}) 
    172180u'<input type="checkbox" name="is_cool" class="pretty" />' 
     
    181189>>> w.render('is_cool', '', attrs={'class': 'special'}) 
    182190u'<input type="checkbox" class="special" name="is_cool" />' 
     191 
     192You can pass 'check_test' to the constructor. This is a callable that takes the 
     193value and returns True if the box should be checked. 
     194>>> w = CheckboxInput(check_test=lambda value: value.startswith('hello')) 
     195>>> w.render('greeting', '') 
     196u'<input type="checkbox" name="greeting" />' 
     197>>> w.render('greeting', 'hello') 
     198u'<input checked="checked" type="checkbox" name="greeting" value="hello" />' 
     199>>> w.render('greeting', 'hello there') 
     200u'<input checked="checked" type="checkbox" name="greeting" value="hello there" />' 
     201>>> w.render('greeting', 'hello & goodbye') 
     202u'<input checked="checked" type="checkbox" name="greeting" value="hello &amp; goodbye" />' 
     203 
     204A subtlety: If the 'check_test' argument cannot handle a value and raises any 
     205exception during its __call__, then the exception will be swallowed and the box 
     206will not be checked. In this example, the 'check_test' assumes the value has a 
     207startswith() method, which fails for the values True, False and None. 
     208>>> w.render('greeting', True) 
     209u'<input type="checkbox" name="greeting" />' 
     210>>> w.render('greeting', False) 
     211u'<input type="checkbox" name="greeting" />' 
     212>>> w.render('greeting', None) 
     213u'<input type="checkbox" name="greeting" />' 
    183214 
    184215# Select Widget ############################################################### 
     
    489520>>> print w.render('beatles', ['J'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) 
    490521<ul> 
    491 <li><label><input checked="checked" type="checkbox" name="beatlesJ" /> John</label></li> 
    492 <li><label><input type="checkbox" name="beatlesP" /> Paul</label></li> 
    493 <li><label><input type="checkbox" name="beatlesG" /> George</label></li> 
    494 <li><label><input type="checkbox" name="beatlesR" /> Ringo</label></li> 
     522<li><label><input checked="checked" type="checkbox" name="beatles" value="J" /> John</label></li> 
     523<li><label><input type="checkbox" name="beatles" value="P" /> Paul</label></li> 
     524<li><label><input type="checkbox" name="beatles" value="G" /> George</label></li> 
     525<li><label><input type="checkbox" name="beatles" value="R" /> Ringo</label></li> 
    495526</ul> 
    496527>>> print w.render('beatles', ['J', 'P'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) 
    497528<ul> 
    498 <li><label><input checked="checked" type="checkbox" name="beatlesJ" /> John</label></li> 
    499 <li><label><input checked="checked" type="checkbox" name="beatlesP" /> Paul</label></li> 
    500 <li><label><input type="checkbox" name="beatlesG" /> George</label></li> 
    501 <li><label><input type="checkbox" name="beatlesR" /> Ringo</label></li> 
     529<li><label><input checked="checked" type="checkbox" name="beatles" value="J" /> John</label></li> 
     530<li><label><input checked="checked" type="checkbox" name="beatles" value="P" /> Paul</label></li> 
     531<li><label><input type="checkbox" name="beatles" value="G" /> George</label></li> 
     532<li><label><input type="checkbox" name="beatles" value="R" /> Ringo</label></li> 
    502533</ul> 
    503534>>> print w.render('beatles', ['J', 'P', 'R'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) 
    504535<ul> 
    505 <li><label><input checked="checked" type="checkbox" name="beatlesJ" /> John</label></li> 
    506 <li><label><input checked="checked" type="checkbox" name="beatlesP" /> Paul</label></li> 
    507 <li><label><input type="checkbox" name="beatlesG" /> George</label></li> 
    508 <li><label><input checked="checked" type="checkbox" name="beatlesR" /> Ringo</label></li> 
     536<li><label><input checked="checked" type="checkbox" name="beatles" value="J" /> John</label></li> 
     537<li><label><input checked="checked" type="checkbox" name="beatles" value="P" /> Paul</label></li> 
     538<li><label><input type="checkbox" name="beatles" value="G" /> George</label></li> 
     539<li><label><input checked="checked" type="checkbox" name="beatles" value="R" /> Ringo</label></li> 
    509540</ul> 
    510541 
     
    512543>>> print w.render('beatles', None, choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) 
    513544<ul> 
    514 <li><label><input type="checkbox" name="beatlesJ" /> John</label></li> 
    515 <li><label><input type="checkbox" name="beatlesP" /> Paul</label></li> 
    516 <li><label><input type="checkbox" name="beatlesG" /> George</label></li> 
    517 <li><label><input type="checkbox" name="beatlesR" /> Ringo</label></li> 
     545<li><label><input type="checkbox" name="beatles" value="J" /> John</label></li> 
     546<li><label><input type="checkbox" name="beatles" value="P" /> Paul</label></li> 
     547<li><label><input type="checkbox" name="beatles" value="G" /> George</label></li> 
     548<li><label><input type="checkbox" name="beatles" value="R" /> Ringo</label></li> 
    518549</ul> 
    519550 
     
    521552>>> print w.render('beatles', ['John'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) 
    522553<ul> 
    523 <li><label><input type="checkbox" name="beatlesJ" /> John</label></li> 
    524 <li><label><input type="checkbox" name="beatlesP" /> Paul</label></li> 
    525 <li><label><input type="checkbox" name="beatlesG" /> George</label></li> 
    526 <li><label><input type="checkbox" name="beatlesR" /> Ringo</label></li> 
     554<li><label><input type="checkbox" name="beatles" value="J" /> John</label></li> 
     555<li><label><input type="checkbox" name="beatles" value="P" /> Paul</label></li> 
     556<li><label><input type="checkbox" name="beatles" value="G" /> George</label></li> 
     557<li><label><input type="checkbox" name="beatles" value="R" /> Ringo</label></li> 
    527558</ul> 
    528559 
     
    530561>>> print w.render('beatles', ['J', 'G', 'foo'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) 
    531562<ul> 
    532 <li><label><input checked="checked" type="checkbox" name="beatlesJ" /> John</label></li> 
    533 <li><label><input type="checkbox" name="beatlesP" /> Paul</label></li> 
    534 <li><label><input checked="checked" type="checkbox" name="beatlesG" /> George</label></li> 
    535 <li><label><input type="checkbox" name="beatlesR" /> Ringo</label></li> 
     563<li><label><input checked="checked" type="checkbox" name="beatles" value="J" /> John</label></li> 
     564<li><label><input type="checkbox" name="beatles" value="P" /> Paul</label></li> 
     565<li><label><input checked="checked" type="checkbox" name="beatles" value="G" /> George</label></li> 
     566<li><label><input type="checkbox" name="beatles" value="R" /> Ringo</label></li> 
    536567</ul> 
    537568 
     
    539570>>> print w.render('nums', [2], choices=[('1', '1'), ('2', '2'), ('3', '3')]) 
    540571<ul> 
    541 <li><label><input type="checkbox" name="nums1" /> 1</label></li> 
    542 <li><label><input checked="checked" type="checkbox" name="nums2" /> 2</label></li> 
    543 <li><label><input type="checkbox" name="nums3" /> 3</label></li> 
     572<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li> 
     573<li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li> 
     574<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li> 
    544575</ul> 
    545576>>> print w.render('nums', ['2'], choices=[(1, 1), (2, 2), (3, 3)]) 
    546577<ul> 
    547 <li><label><input type="checkbox" name="nums1" /> 1</label></li> 
    548 <li><label><input checked="checked" type="checkbox" name="nums2" /> 2</label></li> 
    549 <li><label><input type="checkbox" name="nums3" /> 3</label></li> 
     578<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li> 
     579<li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li> 
     580<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li> 
    550581</ul> 
    551582>>> print w.render('nums', [2], choices=[(1, 1), (2, 2), (3, 3)]) 
    552583<ul> 
    553 <li><label><input type="checkbox" name="nums1" /> 1</label></li> 
    554 <li><label><input checked="checked" type="checkbox" name="nums2" /> 2</label></li> 
    555 <li><label><input type="checkbox" name="nums3" /> 3</label></li> 
     584<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li> 
     585<li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li> 
     586<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li> 
    556587</ul> 
    557588 
     
    562593>>> print w.render('nums', [2], choices=get_choices()) 
    563594<ul> 
    564 <li><label><input type="checkbox" name="nums0" /> 0</label></li> 
    565 <li><label><input type="checkbox" name="nums1" /> 1</label></li> 
    566 <li><label><input checked="checked" type="checkbox" name="nums2" /> 2</label></li> 
    567 <li><label><input type="checkbox" name="nums3" /> 3</label></li> 
    568 <li><label><input type="checkbox" name="nums4" /> 4</label></li> 
     595<li><label><input type="checkbox" name="nums" value="0" /> 0</label></li> 
     596<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li> 
     597<li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li> 
     598<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li> 
     599<li><label><input type="checkbox" name="nums" value="4" /> 4</label></li> 
    569600</ul> 
    570601 
     
    573604>>> print w.render('nums', [2]) 
    574605<ul> 
    575 <li><label><input type="checkbox" name="nums1" /> 1</label></li> 
    576 <li><label><input checked="checked" type="checkbox" name="nums2" /> 2</label></li> 
    577 <li><label><input type="checkbox" name="nums3" /> 3</label></li> 
     606<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li> 
     607<li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li> 
     608<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li> 
    578609</ul> 
    579610 
     
    581612>>> print w.render('nums', [2], choices=[(4, 4), (5, 5)]) 
    582613<ul> 
    583 <li><label><input type="checkbox" name="nums1" /> 1</label></li> 
    584 <li><label><input checked="checked" type="checkbox" name="nums2" /> 2</label></li> 
    585 <li><label><input type="checkbox" name="nums3" /> 3</label></li> 
    586 <li><label><input type="checkbox" name="nums4" /> 4</label></li> 
    587 <li><label><input type="checkbox" name="nums5" /> 5</label></li> 
     614<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li> 
     615<li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li> 
     616<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li> 
     617<li><label><input type="checkbox" name="nums" value="4" /> 4</label></li> 
     618<li><label><input type="checkbox" name="nums" value="5" /> 5</label></li> 
    588619</ul> 
    589620 
    590621>>> w.render('nums', ['ŠĐĆŽćžšđ'], choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')]) 
    591 u'<ul>\n<li><label><input type="checkbox" name="nums1" /> 1</label></li>\n<li><label><input type="checkbox" name="nums2" /> 2</label></li>\n<li><label><input type="checkbox" name="nums3" /> 3</label></li>\n<li><label><input checked="checked" type="checkbox" name="nums\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" /> \u0160\u0110abc\u0106\u017d\u0107\u017e\u0161\u0111</label></li>\n<li><label><input type="checkbox" name="nums\u0107\u017e\u0161\u0111" /> abc\u0107\u017e\u0161\u0111</label></li>\n</ul>' 
     622u'<ul>\n<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li>\n<li><label><input type="checkbox" name="nums" value="2" /> 2</label></li>\n<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li>\n<li><label><input checked="checked" type="checkbox" name="nums" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" /> \u0160\u0110abc\u0106\u017d\u0107\u017e\u0161\u0111</label></li>\n<li><label><input type="checkbox" name="nums" value="\u0107\u017e\u0161\u0111" /> abc\u0107\u017e\u0161\u0111</label></li>\n</ul>' 
    592623 
    593624########## 
     
    16001631>>> print f['composers'] 
    16011632<ul> 
    1602 <li><label><input type="checkbox" name="composersJ" /> John Lennon</label></li> 
    1603 <li><label><input type="checkbox" name="composersP" /> Paul McCartney</label></li> 
     1633<li><label><input type="checkbox" name="composers" value="J" /> John Lennon</label></li> 
     1634<li><label><input type="checkbox" name="composers" value="P" /> Paul McCartney</label></li> 
    16041635</ul> 
    16051636>>> f = SongForm({'composers': ['J']}) 
    16061637>>> print f['composers'] 
    16071638<ul> 
    1608 <li><label><input checked="checked" type="checkbox" name="composersJ" /> John Lennon</label></li> 
    1609 <li><label><input type="checkbox" name="composersP" /> Paul McCartney</label></li> 
     1639<li><label><input checked="checked" type="checkbox" name="composers" value="J" /> John Lennon</label></li> 
     1640<li><label><input type="checkbox" name="composers" value="P" /> Paul McCartney</label></li> 
    16101641</ul> 
    16111642>>> f = SongForm({'composers': ['J', 'P']}) 
    16121643>>> print f['composers'] 
    16131644<ul> 
    1614 <li><label><input checked="checked" type="checkbox" name="composersJ" /> John Lennon</label></li> 
    1615 <li><label><input checked="checked" type="checkbox" name="composersP" /> Paul McCartney</label></li> 
    1616 </ul> 
    1617  
    1618 When using CheckboxSelectMultiple, the framework automatically converts the 
    1619 data in clean_data to a list of values, rather than the underlying HTML form 
    1620 field name. 
     1645<li><label><input checked="checked" type="checkbox" name="composers" value="J" /> John Lennon</label></li> 
     1646<li><label><input checked="checked" type="checkbox" name="composers" value="P" /> Paul McCartney</label></li> 
     1647</ul> 
     1648 
     1649When using CheckboxSelectMultiple, the framework expects a list of input and 
     1650returns a list of input. 
    16211651>>> f = SongForm({'name': 'Yesterday'}) 
    16221652>>> f.errors 
    16231653{'composers': [u'This field is required.']} 
    1624 >>> f = SongForm({'name': 'Yesterday', 'composersJ': 'on'}) 
     1654>>> f = SongForm({'name': 'Yesterday', 'composers': ['J']}) 
    16251655>>> f.errors 
    16261656{} 
    16271657>>> f.clean_data 
    16281658{'composers': [u'J'], 'name': u'Yesterday'} 
    1629 >>> f = SongForm({'name': 'Yesterday', 'composersJ': 'on', 'composersP': 'on'}) 
     1659>>> f = SongForm({'name': 'Yesterday', 'composers': ['J', 'P']}) 
    16301660>>> f.errors 
    16311661{}