Ticket #4592: 4592-3.diff
File 4592-3.diff, 9.2 KB (added by , 17 years ago) |
---|
-
django/newforms/widgets.py
215 215 return data.getlist(name) 216 216 return data.get(name, None) 217 217 218 class RadioInput(StrAndUnicode): 219 "An object used by RadioFieldRenderer that represents a single <input type='radio'>." 218 class ChoiceInput(StrAndUnicode): 219 input_type = None # Subclasses must define this. 220 221 "An object used by ChoiceFieldRenderer that represents a single radio or checkbox input." 220 222 def __init__(self, name, value, attrs, choice, index): 221 223 self.name, self.value = name, value 222 224 self.attrs = attrs … … 233 235 def tag(self): 234 236 if 'id' in self.attrs: 235 237 self.attrs['id'] = '%s_%s' % (self.attrs['id'], self.index) 236 final_attrs = dict(self.attrs, type= 'radio', name=self.name, value=self.choice_value)238 final_attrs = dict(self.attrs, type=self.input_type, name=self.name, value=self.choice_value) 237 239 if self.is_checked(): 238 240 final_attrs['checked'] = 'checked' 239 241 return u'<input%s />' % flatatt(final_attrs) 240 242 241 class RadioFieldRenderer(StrAndUnicode): 242 "An object used by RadioSelect to enable customization of radio widgets." 243 def __init__(self, name, value, attrs, choices): 243 class RadioChoiceInput(ChoiceInput): 244 input_type = 'radio' 245 246 class CheckboxChoiceInput(ChoiceInput): 247 input_type = 'checkbox' 248 249 def is_checked(self): 250 return self.choice_value in self.value 251 252 class ChoiceFieldRenderer(StrAndUnicode): 253 "An object used to enable customization of radio and checkbox widgets." 254 def __init__(self, name, value, attrs, choices, choice_widget=ChoiceInput): 244 255 self.name, self.value, self.attrs = name, value, attrs 245 256 self.choices = choices 257 self.choice_widget = choice_widget 246 258 247 259 def __iter__(self): 248 260 for i, choice in enumerate(self.choices): 249 yield RadioInput(self.name, self.value, self.attrs.copy(), choice, i)261 yield self.choice_widget(self.name, self.value, self.attrs.copy(), choice, i) 250 262 251 263 def __getitem__(self, idx): 252 264 choice = self.choices[idx] # Let the IndexError propogate 253 return RadioInput(self.name, self.value, self.attrs.copy(), choice, idx)265 return self.choice_widget(self.name, self.value, self.attrs.copy(), choice, idx) 254 266 255 267 def __unicode__(self): 256 "Outputs a <ul> for this set of radiofields."268 "Outputs a <ul> for this set of choice fields." 257 269 return u'<ul>\n%s\n</ul>' % u'\n'.join([u'<li>%s</li>' % force_unicode(w) for w in self]) 258 270 259 271 class RadioSelect(Select): 260 272 def render(self, name, value, attrs=None, choices=()): 261 "Returns a RadioFieldRenderer instance rather than a Unicode string."273 "Returns a ChoiceFieldRenderer instance rather than a Unicode string." 262 274 if value is None: value = '' 263 275 str_value = force_unicode(value) # Normalize to string. 264 276 final_attrs = self.build_attrs(attrs) 265 return RadioFieldRenderer(name, str_value, final_attrs, list(chain(self.choices, choices)))277 return ChoiceFieldRenderer(name, str_value, final_attrs, list(chain(self.choices, choices)), choice_widget=RadioChoiceInput) 266 278 267 279 def id_for_label(self, id_): 268 280 # RadioSelect is represented by multiple <input type="radio"> fields, … … 276 288 277 289 class CheckboxSelectMultiple(SelectMultiple): 278 290 def render(self, name, value, attrs=None, choices=()): 291 "Returns a ChoiceFieldRenderer instance rather than a Unicode string." 279 292 if value is None: value = [] 280 has_id = attrs and 'id' in attrs293 str_values = set([force_unicode(v) for v in value]) # Normalize to strings. 281 294 final_attrs = self.build_attrs(attrs, name=name) 282 output = [u'<ul>'] 283 str_values = set([force_unicode(v) for v in value]) # Normalize to strings. 284 for i, (option_value, option_label) in enumerate(chain(self.choices, choices)): 285 # If an ID attribute was given, add a numeric index as a suffix, 286 # so that the checkboxes don't all have the same ID attribute. 287 if has_id: 288 final_attrs = dict(final_attrs, id='%s_%s' % (attrs['id'], i)) 289 cb = CheckboxInput(final_attrs, check_test=lambda value: value in str_values) 290 option_value = force_unicode(option_value) 291 rendered_cb = cb.render(name, option_value) 292 output.append(u'<li><label>%s %s</label></li>' % (rendered_cb, escape(force_unicode(option_label)))) 293 output.append(u'</ul>') 294 return u'\n'.join(output) 295 return ChoiceFieldRenderer(name, str_values, final_attrs, list(chain(self.choices, choices)), choice_widget=CheckboxChoiceInput) 295 296 296 297 def id_for_label(self, id_): 297 298 # See the comment for RadioSelect.id_for_label() -
tests/regressiontests/forms/tests.py
614 614 <li><label><input type="radio" name="num" value="5" /> 5</label></li> 615 615 </ul> 616 616 617 The render() method returns a RadioFieldRenderer object, whose str() is a <ul>.617 The render() method returns a ChoiceFieldRenderer object, whose str() is a <ul>. 618 618 You can manipulate that object directly to customize the way the RadioSelect 619 619 is rendered. 620 620 >>> w = RadioSelect() … … 644 644 beatle J G George False 645 645 beatle J R Ringo False 646 646 647 A RadioFieldRenderer object also allows index access to individual RadioInput647 A ChoiceFieldRenderer object also allows index access to individual RadioInput 648 648 objects. 649 649 >>> w = RadioSelect() 650 650 >>> r = w.render('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) … … 792 792 <li><label><input type="checkbox" name="nums" value="5" /> 5</label></li> 793 793 </ul> 794 794 795 >>> w.render('nums', ['ŠĐĆŽćžšđ'], choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')]) 795 The render() method returns a ChoiceFieldRenderer object, whose str() is a <ul>. 796 You can manipulate that object directly to customize the way the RadioSelect 797 is rendered. 798 >>> w2 = CheckboxSelectMultiple() 799 >>> r = w2.render('beatle', ['J', 'G'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) 800 >>> for inp in r: 801 ... print inp 802 <label><input checked="checked" type="checkbox" name="beatle" value="J" /> John</label> 803 <label><input type="checkbox" name="beatle" value="P" /> Paul</label> 804 <label><input checked="checked" type="checkbox" name="beatle" value="G" /> George</label> 805 <label><input type="checkbox" name="beatle" value="R" /> Ringo</label> 806 >>> for inp in r: 807 ... print '%s<br />' % inp 808 <label><input checked="checked" type="checkbox" name="beatle" value="J" /> John</label><br /> 809 <label><input type="checkbox" name="beatle" value="P" /> Paul</label><br /> 810 <label><input checked="checked" type="checkbox" name="beatle" value="G" /> George</label><br /> 811 <label><input type="checkbox" name="beatle" value="R" /> Ringo</label><br /> 812 >>> for inp in r: 813 ... print '<p>%s %s</p>' % (inp.tag(), inp.choice_label) 814 <p><input checked="checked" type="checkbox" name="beatle" value="J" /> John</p> 815 <p><input type="checkbox" name="beatle" value="P" /> Paul</p> 816 <p><input checked="checked" type="checkbox" name="beatle" value="G" /> George</p> 817 <p><input type="checkbox" name="beatle" value="R" /> Ringo</p> 818 >>> for inp in r: 819 ... print '%s %s %s %s %s' % (inp.name, inp.value, inp.choice_value, inp.choice_label, inp.is_checked()) 820 beatle set([u'J', u'G']) J John True 821 beatle set([u'J', u'G']) P Paul False 822 beatle set([u'J', u'G']) G George True 823 beatle set([u'J', u'G']) R Ringo False 824 825 A ChoiceFieldRenderer object also allows index access to individual RadioInput 826 objects. 827 >>> w2 = CheckboxSelectMultiple() 828 >>> r = w2.render('beatle', ['J'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) 829 >>> print r[1] 830 <label><input type="checkbox" name="beatle" value="P" /> Paul</label> 831 >>> print r[0] 832 <label><input checked="checked" type="checkbox" name="beatle" value="J" /> John</label> 833 >>> r[0].is_checked() 834 True 835 >>> r[1].is_checked() 836 False 837 >>> r[1].name, r[1].value, r[1].choice_value, r[1].choice_label 838 ('beatle', set([u'J']), u'P', u'Paul') 839 >>> r[10] 840 Traceback (most recent call last): 841 ... 842 IndexError: list index out of range 843 844 >>> unicode(w.render('nums', ['ŠĐĆŽćžšđ'], choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')])) 796 845 u'<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>' 797 846 798 847 # MultiWidget #################################################################