diff options
| author | Russell Keith-Magee <russell@keith-magee.com> | 2008-07-19 07:53:02 +0000 |
|---|---|---|
| committer | Russell Keith-Magee <russell@keith-magee.com> | 2008-07-19 07:53:02 +0000 |
| commit | 649463dd348abd6d0cab890e2372e88fc452128e (patch) | |
| tree | f554f6163a30f9d0dfdb996a8322ac73d565a999 /django/forms/widgets.py | |
| parent | b5b0febc4cd5ad51aeb1ef7b37aaca6a7632519d (diff) | |
Fixed #4412 -- Added support for optgroups, both in the model when defining choices, and in the form field and widgets when the optgroups are displayed. Thanks to Matt McClanahan <cardinal@dodds.net>, Tai Lee <real.human@mrmachine.net> and SmileyChris for their contributions at various stages in the life of this ticket.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7977 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django/forms/widgets.py')
| -rw-r--r-- | django/forms/widgets.py | 52 |
1 files changed, 29 insertions, 23 deletions
diff --git a/django/forms/widgets.py b/django/forms/widgets.py index 2c9f3c2eba..cc065d71d8 100644 --- a/django/forms/widgets.py +++ b/django/forms/widgets.py @@ -345,17 +345,32 @@ class Select(Widget): if value is None: value = '' final_attrs = self.build_attrs(attrs, name=name) output = [u'<select%s>' % flatatt(final_attrs)] - # Normalize to string. - str_value = force_unicode(value) - for option_value, option_label in chain(self.choices, choices): - option_value = force_unicode(option_value) - selected_html = (option_value == str_value) and u' selected="selected"' or '' - output.append(u'<option value="%s"%s>%s</option>' % ( - escape(option_value), selected_html, - conditional_escape(force_unicode(option_label)))) - output.append(u'</select>') + options = self.render_options(choices, [value]) + if options: + output.append(options) + output.append('</select>') return mark_safe(u'\n'.join(output)) + def render_options(self, choices, selected_choices): + def render_option(option_value, option_label): + option_value = force_unicode(option_value) + selected_html = (option_value in selected_choices) and u' selected="selected"' or '' + return u'<option value="%s"%s>%s</option>' % ( + escape(option_value), selected_html, + conditional_escape(force_unicode(option_label))) + # Normalize to strings. + 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)): + output.append(u'<optgroup label="%s">' % escape(force_unicode(option_value))) + for option in option_label: + output.append(render_option(*option)) + output.append(u'</optgroup>') + else: + output.append(render_option(option_value, option_label)) + return u'\n'.join(output) + class NullBooleanSelect(Select): """ A Select Widget intended to be used with NullBooleanField. @@ -380,24 +395,15 @@ class NullBooleanSelect(Select): # same thing as False. return bool(initial) != bool(data) -class SelectMultiple(Widget): - def __init__(self, attrs=None, choices=()): - super(SelectMultiple, self).__init__(attrs) - # choices can be any iterable - self.choices = choices - +class SelectMultiple(Select): def render(self, name, value, attrs=None, choices=()): if value is None: value = [] final_attrs = self.build_attrs(attrs, name=name) output = [u'<select multiple="multiple"%s>' % flatatt(final_attrs)] - str_values = set([force_unicode(v) for v in value]) # Normalize to strings. - for option_value, option_label in chain(self.choices, choices): - option_value = force_unicode(option_value) - selected_html = (option_value in str_values) and ' selected="selected"' or '' - output.append(u'<option value="%s"%s>%s</option>' % ( - escape(option_value), selected_html, - conditional_escape(force_unicode(option_label)))) - output.append(u'</select>') + options = self.render_options(choices, value) + if options: + output.append(options) + output.append('</select>') return mark_safe(u'\n'.join(output)) def value_from_datadict(self, data, files, name): |
