Author: SmileyChris
Date: 2011-09-17 21:09:44 -0700 (Sat, 17 Sep 2011)
New Revision: 16848

Modified:
   django/trunk/django/forms/widgets.py
   django/trunk/tests/regressiontests/forms/tests/widgets.py
Log:
Fixes #8103 -- Select widget should only allow for one selected option

Modified: django/trunk/django/forms/widgets.py
===================================================================
--- django/trunk/django/forms/widgets.py        2011-09-17 23:01:46 UTC (rev 
16847)
+++ django/trunk/django/forms/widgets.py        2011-09-18 04:09:44 UTC (rev 
16848)
@@ -499,6 +499,8 @@
         return bool(initial) != bool(data)
 
 class Select(Widget):
+    allow_multiple_selected = False
+
     def __init__(self, attrs=None, choices=()):
         super(Select, self).__init__(attrs)
         # choices can be any iterable, but we may need to render this widget
@@ -518,14 +520,20 @@
 
     def render_option(self, selected_choices, option_value, option_label):
         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>' % (
             escape(option_value), selected_html,
             conditional_escape(force_unicode(option_label)))
 
     def render_options(self, choices, selected_choices):
         # 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 = []
         for option_value, option_label in chain(self.choices, choices):
             if isinstance(option_label, (list, tuple)):
@@ -571,6 +579,8 @@
         return initial != data
 
 class SelectMultiple(Select):
+    allow_multiple_selected = True
+
     def render(self, name, value, attrs=None, choices=()):
         if value is None: value = []
         final_attrs = self.build_attrs(attrs, name=name)

Modified: django/trunk/tests/regressiontests/forms/tests/widgets.py
===================================================================
--- django/trunk/tests/regressiontests/forms/tests/widgets.py   2011-09-17 
23:01:46 UTC (rev 16847)
+++ django/trunk/tests/regressiontests/forms/tests/widgets.py   2011-09-18 
04:09:44 UTC (rev 16848)
@@ -12,7 +12,6 @@
 from django.utils.unittest import TestCase
 
 
-
 class FormsWidgetTestCase(TestCase):
     # 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
@@ -257,6 +256,15 @@
 <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>""")
+
         # The value is compared to its str():
         self.assertEqual(w.render('num', 2, choices=[('1', '1'), ('2', '2'), 
('3', '3')]), """<select name="num">
 <option value="1">1</option>
@@ -440,6 +448,15 @@
 <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>""")
+
         # If multiple values are given, but some of them are not valid, the 
valid ones are selected:
         self.assertEqual(w.render('beatles', ['J', 'G', 'foo'], choices=(('J', 
'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))), """<select 
multiple="multiple" name="beatles">
 <option value="J" selected="selected">John</option>

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en.

Reply via email to