Fixed #20931 -- Fixed select widgets nested choice rendering
ChoiceFieldRenderer was not rendering nested choices. Added recursion to ChoiceFieldRenderer to take nested choices and render them as <ul>'s.
This commit is contained in:
parent
5866a49369
commit
a834bc84d8
1
AUTHORS
1
AUTHORS
|
@ -89,6 +89,7 @@ answer newbie questions, and generally made Django that much better:
|
||||||
David Avsajanishvili <avsd05@gmail.com>
|
David Avsajanishvili <avsd05@gmail.com>
|
||||||
Mike Axiak <axiak@mit.edu>
|
Mike Axiak <axiak@mit.edu>
|
||||||
Niran Babalola <niran@niran.org>
|
Niran Babalola <niran@niran.org>
|
||||||
|
Christopher Babiak <chrisbabiak@gmail.com>
|
||||||
Vitaly Babiy <vbabiy86@gmail.com>
|
Vitaly Babiy <vbabiy86@gmail.com>
|
||||||
Morten Bagai <m@bagai.com>
|
Morten Bagai <m@bagai.com>
|
||||||
Jeff Balogh <jbalogh@mozilla.com>
|
Jeff Balogh <jbalogh@mozilla.com>
|
||||||
|
|
|
@ -665,10 +665,6 @@ class ChoiceFieldRenderer(object):
|
||||||
self.attrs = attrs
|
self.attrs = attrs
|
||||||
self.choices = choices
|
self.choices = choices
|
||||||
|
|
||||||
def __iter__(self):
|
|
||||||
for i, choice in enumerate(self.choices):
|
|
||||||
yield self.choice_input_class(self.name, self.value, self.attrs.copy(), choice, i)
|
|
||||||
|
|
||||||
def __getitem__(self, idx):
|
def __getitem__(self, idx):
|
||||||
choice = self.choices[idx] # Let the IndexError propogate
|
choice = self.choices[idx] # Let the IndexError propogate
|
||||||
return self.choice_input_class(self.name, self.value, self.attrs.copy(), choice, idx)
|
return self.choice_input_class(self.name, self.value, self.attrs.copy(), choice, idx)
|
||||||
|
@ -685,8 +681,23 @@ class ChoiceFieldRenderer(object):
|
||||||
id_ = self.attrs.get('id', None)
|
id_ = self.attrs.get('id', None)
|
||||||
start_tag = format_html('<ul id="{0}">', id_) if id_ else '<ul>'
|
start_tag = format_html('<ul id="{0}">', id_) if id_ else '<ul>'
|
||||||
output = [start_tag]
|
output = [start_tag]
|
||||||
for widget in self:
|
for i, choice in enumerate(self.choices):
|
||||||
output.append(format_html('<li>{0}</li>', force_text(widget)))
|
choice_value, choice_label = choice
|
||||||
|
if isinstance(choice_label, (tuple,list)):
|
||||||
|
attrs_plus = self.attrs.copy()
|
||||||
|
if id_:
|
||||||
|
attrs_plus['id'] += '_{0}'.format(i)
|
||||||
|
sub_ul_renderer = ChoiceFieldRenderer(name=self.name,
|
||||||
|
value=self.value,
|
||||||
|
attrs=attrs_plus,
|
||||||
|
choices=choice_label)
|
||||||
|
sub_ul_renderer.choice_input_class = self.choice_input_class
|
||||||
|
output.append(format_html('<li>{0}{1}</li>', choice_value,
|
||||||
|
sub_ul_renderer.render()))
|
||||||
|
else:
|
||||||
|
w = self.choice_input_class(self.name, self.value,
|
||||||
|
self.attrs.copy(), choice, i)
|
||||||
|
output.append(format_html('<li>{0}</li>', force_text(w)))
|
||||||
output.append('</ul>')
|
output.append('</ul>')
|
||||||
return mark_safe('\n'.join(output))
|
return mark_safe('\n'.join(output))
|
||||||
|
|
||||||
|
|
|
@ -695,6 +695,37 @@ beatle J R Ringo False""")
|
||||||
<li><label for="bar_1"><input type="radio" id="bar_1" value="P" name="beatle" /> Paul</label></li>
|
<li><label for="bar_1"><input type="radio" id="bar_1" value="P" name="beatle" /> Paul</label></li>
|
||||||
<li><label for="bar_2"><input type="radio" id="bar_2" value="G" name="beatle" /> George</label></li>
|
<li><label for="bar_2"><input type="radio" id="bar_2" value="G" name="beatle" /> George</label></li>
|
||||||
<li><label for="bar_3"><input type="radio" id="bar_3" value="R" name="beatle" /> Ringo</label></li>
|
<li><label for="bar_3"><input type="radio" id="bar_3" value="R" name="beatle" /> Ringo</label></li>
|
||||||
|
</ul>""")
|
||||||
|
|
||||||
|
def test_nested_choices(self):
|
||||||
|
# Choices can be nested for radio buttons:
|
||||||
|
w = RadioSelect()
|
||||||
|
w.choices=(('unknown', 'Unknown'), ('Audio', (('vinyl', 'Vinyl'), ('cd', 'CD'))), ('Video', (('vhs', 'VHS'), ('dvd', 'DVD'))))
|
||||||
|
self.assertHTMLEqual(w.render('nestchoice', 'dvd', attrs={'id':'media'}), """<ul id="media">
|
||||||
|
<li><label for="media_0"><input id="media_0" name="nestchoice" type="radio" value="unknown" /> Unknown</label></li>
|
||||||
|
<li>Audio<ul id="media_1">
|
||||||
|
<li><label for="media_1_0"><input id="media_1_0" name="nestchoice" type="radio" value="vinyl" /> Vinyl</label></li>
|
||||||
|
<li><label for="media_1_1"><input id="media_1_1" name="nestchoice" type="radio" value="cd" /> CD</label></li>
|
||||||
|
</ul></li>
|
||||||
|
<li>Video<ul id="media_2">
|
||||||
|
<li><label for="media_2_0"><input id="media_2_0" name="nestchoice" type="radio" value="vhs" /> VHS</label></li>
|
||||||
|
<li><label for="media_2_1"><input checked="checked" id="media_2_1" name="nestchoice" type="radio" value="dvd" /> DVD</label></li>
|
||||||
|
</ul></li>
|
||||||
|
</ul>""")
|
||||||
|
|
||||||
|
# Choices can be nested for checkboxes:
|
||||||
|
w = CheckboxSelectMultiple()
|
||||||
|
w.choices=(('unknown', 'Unknown'), ('Audio', (('vinyl', 'Vinyl'), ('cd', 'CD'))), ('Video', (('vhs', 'VHS'), ('dvd', 'DVD'))))
|
||||||
|
self.assertHTMLEqual(w.render('nestchoice', ('vinyl', 'dvd'), attrs={'id':'media'}), """<ul id="media">
|
||||||
|
<li><label for="media_0"><input id="media_0" name="nestchoice" type="checkbox" value="unknown" /> Unknown</label></li>
|
||||||
|
<li>Audio<ul id="media_1">
|
||||||
|
<li><label for="media_1_0"><input checked="checked" id="media_1_0" name="nestchoice" type="checkbox" value="vinyl" /> Vinyl</label></li>
|
||||||
|
<li><label for="media_1_1"><input id="media_1_1" name="nestchoice" type="checkbox" value="cd" /> CD</label></li>
|
||||||
|
</ul></li>
|
||||||
|
<li>Video<ul id="media_2">
|
||||||
|
<li><label for="media_2_0"><input id="media_2_0" name="nestchoice" type="checkbox" value="vhs" /> VHS</label></li>
|
||||||
|
<li><label for="media_2_1"><input checked="checked" id="media_2_1" name="nestchoice" type="checkbox" value="dvd" /> DVD</label></li>
|
||||||
|
</ul></li>
|
||||||
</ul>""")
|
</ul>""")
|
||||||
|
|
||||||
def test_checkboxselectmultiple(self):
|
def test_checkboxselectmultiple(self):
|
||||||
|
|
Loading…
Reference in New Issue