Django

Code

Ticket #3442: widgets.diff

File widgets.diff, 2.2 kB (added by tbarta@gmail.com, 1 year ago)

patch to add groupedSelect widget that works with existing ChoiceField class

  • widgets.py

    old new  
    22Extra HTML Widget classes 
    33""" 
    44 
     5from django.utils.html import escape 
     6from itertools import chain 
     7from django.newforms.util import flatatt, smart_unicode 
    58from django.newforms.widgets import Widget, Select 
    69from django.utils.dates import MONTHS 
    710import datetime 
    811 
    9 __all__ = ('SelectDateWidget',
     12__all__ = ('SelectDateWidget', 'GroupedSelect'
    1013 
    1114class SelectDateWidget(Widget): 
    1215    """ 
     
    5760        if y and m and d: 
    5861            return '%s-%s-%s' % (y, m, d) 
    5962        return None 
     63  
     64class GroupedSelect(Select): 
     65    def __init__(self, attrs=None, groups=(), choices=()): 
     66        super(GroupedSelect, self).__init__(attrs, choices) 
     67        # groups maps from 'group name' to a list of values in that group 
     68        # to preserve ordering, it's a list-of-tuples instead of a dict 
     69        self.groups = groups 
     70 
     71    def render(self, name, value, attrs=None, choices=()): 
     72        if value is None: value = '' 
     73        final_attrs = self.build_attrs(attrs, name=name) 
     74        output = [u'<select%s>' % flatatt(final_attrs)] 
     75        str_value = smart_unicode(value) # Normalize to string. 
     76        allchoices = dict([(smart_unicode(k), smart_unicode(v)) 
     77            for k, v in chain(self.choices, choices)]) 
     78        for group_label, members in self.groups: 
     79            group_label = smart_unicode(group_label) 
     80            output.append(u'<optgroup label="%s">' % escape(group_label)) 
     81            for option_value in members: 
     82                option_value = smart_unicode(option_value) 
     83                try: 
     84                    option_label = allchoices[option_value] 
     85                except KeyError: 
     86                    continue # silently ignore missing elements from the group 
     87                selected_html = (option_value == str_value) and u' selected="selected"' or '' 
     88                output.append(u'<option value="%s"%s>%s</option>' % (escape(option_value), selected_html, escape(option_label))) 
     89            output.append(u'</optgroup>') 
     90        output.append(u'</select>') 
     91        return u'\n'.join(output) 
     92