Fixes #8103 -- Select widget should only allow for one selected option
git-svn-id: http://code.djangoproject.com/svn/django/trunk@16848 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
1ec25c4fb7
commit
e63fa0ff83
|
@ -499,6 +499,8 @@ class CheckboxInput(Widget):
|
||||||
return bool(initial) != bool(data)
|
return bool(initial) != bool(data)
|
||||||
|
|
||||||
class Select(Widget):
|
class Select(Widget):
|
||||||
|
allow_multiple_selected = False
|
||||||
|
|
||||||
def __init__(self, attrs=None, choices=()):
|
def __init__(self, attrs=None, choices=()):
|
||||||
super(Select, self).__init__(attrs)
|
super(Select, self).__init__(attrs)
|
||||||
# choices can be any iterable, but we may need to render this widget
|
# choices can be any iterable, but we may need to render this widget
|
||||||
|
@ -518,14 +520,20 @@ class Select(Widget):
|
||||||
|
|
||||||
def render_option(self, selected_choices, option_value, option_label):
|
def render_option(self, selected_choices, option_value, option_label):
|
||||||
option_value = force_unicode(option_value)
|
option_value = force_unicode(option_value)
|
||||||
selected_html = (option_value in selected_choices) and u' selected="selected"' or ''
|
if option_value in selected_choices:
|
||||||
|
selected_html = u' selected="selected"'
|
||||||
|
if not self.allow_multiple_selected:
|
||||||
|
# Only allow for a single selection.
|
||||||
|
selected_choices.remove(option_value)
|
||||||
|
else:
|
||||||
|
selected_html = ''
|
||||||
return u'<option value="%s"%s>%s</option>' % (
|
return u'<option value="%s"%s>%s</option>' % (
|
||||||
escape(option_value), selected_html,
|
escape(option_value), selected_html,
|
||||||
conditional_escape(force_unicode(option_label)))
|
conditional_escape(force_unicode(option_label)))
|
||||||
|
|
||||||
def render_options(self, choices, selected_choices):
|
def render_options(self, choices, selected_choices):
|
||||||
# Normalize to strings.
|
# Normalize to strings.
|
||||||
selected_choices = set([force_unicode(v) for v in selected_choices])
|
selected_choices = set(force_unicode(v) for v in selected_choices)
|
||||||
output = []
|
output = []
|
||||||
for option_value, option_label in chain(self.choices, choices):
|
for option_value, option_label in chain(self.choices, choices):
|
||||||
if isinstance(option_label, (list, tuple)):
|
if isinstance(option_label, (list, tuple)):
|
||||||
|
@ -571,6 +579,8 @@ class NullBooleanSelect(Select):
|
||||||
return initial != data
|
return initial != data
|
||||||
|
|
||||||
class SelectMultiple(Select):
|
class SelectMultiple(Select):
|
||||||
|
allow_multiple_selected = True
|
||||||
|
|
||||||
def render(self, name, value, attrs=None, choices=()):
|
def render(self, name, value, attrs=None, choices=()):
|
||||||
if value is None: value = []
|
if value is None: value = []
|
||||||
final_attrs = self.build_attrs(attrs, name=name)
|
final_attrs = self.build_attrs(attrs, name=name)
|
||||||
|
|
|
@ -12,7 +12,6 @@ from django.utils.translation import activate, deactivate
|
||||||
from django.utils.unittest import TestCase
|
from django.utils.unittest import TestCase
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class FormsWidgetTestCase(TestCase):
|
class FormsWidgetTestCase(TestCase):
|
||||||
# Each Widget class corresponds to an HTML form widget. A Widget knows how to
|
# Each Widget class corresponds to an HTML form widget. A Widget knows how to
|
||||||
# render itself, given a field name and some data. Widgets don't perform
|
# render itself, given a field name and some data. Widgets don't perform
|
||||||
|
@ -255,6 +254,15 @@ class FormsWidgetTestCase(TestCase):
|
||||||
<option value="P">Paul</option>
|
<option value="P">Paul</option>
|
||||||
<option value="G">George</option>
|
<option value="G">George</option>
|
||||||
<option value="R">Ringo</option>
|
<option value="R">Ringo</option>
|
||||||
|
</select>""")
|
||||||
|
|
||||||
|
# Only one option can be selected, see #8103:
|
||||||
|
self.assertEqual(w.render('choices', '0', choices=(('0', '0'), ('1', '1'), ('2', '2'), ('3', '3'), ('0', 'extra'))), """<select name="choices">
|
||||||
|
<option value="0" selected="selected">0</option>
|
||||||
|
<option value="1">1</option>
|
||||||
|
<option value="2">2</option>
|
||||||
|
<option value="3">3</option>
|
||||||
|
<option value="0">extra</option>
|
||||||
</select>""")
|
</select>""")
|
||||||
|
|
||||||
# The value is compared to its str():
|
# The value is compared to its str():
|
||||||
|
@ -438,6 +446,15 @@ class FormsWidgetTestCase(TestCase):
|
||||||
<option value="P">Paul</option>
|
<option value="P">Paul</option>
|
||||||
<option value="G">George</option>
|
<option value="G">George</option>
|
||||||
<option value="R">Ringo</option>
|
<option value="R">Ringo</option>
|
||||||
|
</select>""")
|
||||||
|
|
||||||
|
# Multiple options (with the same value) can be selected, see #8103:
|
||||||
|
self.assertEqual(w.render('choices', ['0'], choices=(('0', '0'), ('1', '1'), ('2', '2'), ('3', '3'), ('0', 'extra'))), """<select multiple="multiple" name="choices">
|
||||||
|
<option value="0" selected="selected">0</option>
|
||||||
|
<option value="1">1</option>
|
||||||
|
<option value="2">2</option>
|
||||||
|
<option value="3">3</option>
|
||||||
|
<option value="0" selected="selected">extra</option>
|
||||||
</select>""")
|
</select>""")
|
||||||
|
|
||||||
# If multiple values are given, but some of them are not valid, the valid ones are selected:
|
# If multiple values are given, but some of them are not valid, the valid ones are selected:
|
||||||
|
|
Loading…
Reference in New Issue