app/django/forms/extras/widgets.py
changeset 323 ff1a9aa48cfd
equal deleted inserted replaced
322:6641e941ef1e 323:ff1a9aa48cfd
       
     1 """
       
     2 Extra HTML Widget classes
       
     3 """
       
     4 
       
     5 import datetime
       
     6 import re
       
     7 
       
     8 from django.forms.widgets import Widget, Select
       
     9 from django.utils.dates import MONTHS
       
    10 from django.utils.safestring import mark_safe
       
    11 
       
    12 __all__ = ('SelectDateWidget',)
       
    13 
       
    14 RE_DATE = re.compile(r'(\d{4})-(\d\d?)-(\d\d?)$')
       
    15 
       
    16 class SelectDateWidget(Widget):
       
    17     """
       
    18     A Widget that splits date input into three <select> boxes.
       
    19 
       
    20     This also serves as an example of a Widget that has more than one HTML
       
    21     element and hence implements value_from_datadict.
       
    22     """
       
    23     month_field = '%s_month'
       
    24     day_field = '%s_day'
       
    25     year_field = '%s_year'
       
    26 
       
    27     def __init__(self, attrs=None, years=None):
       
    28         # years is an optional list/tuple of years to use in the "year" select box.
       
    29         self.attrs = attrs or {}
       
    30         if years:
       
    31             self.years = years
       
    32         else:
       
    33             this_year = datetime.date.today().year
       
    34             self.years = range(this_year, this_year+10)
       
    35 
       
    36     def render(self, name, value, attrs=None):
       
    37         try:
       
    38             year_val, month_val, day_val = value.year, value.month, value.day
       
    39         except AttributeError:
       
    40             year_val = month_val = day_val = None
       
    41             if isinstance(value, basestring):
       
    42                 match = RE_DATE.match(value)
       
    43                 if match:
       
    44                     year_val, month_val, day_val = [int(v) for v in match.groups()]
       
    45 
       
    46         output = []
       
    47 
       
    48         if 'id' in self.attrs:
       
    49             id_ = self.attrs['id']
       
    50         else:
       
    51             id_ = 'id_%s' % name
       
    52 
       
    53         month_choices = MONTHS.items()
       
    54         month_choices.sort()
       
    55         local_attrs = self.build_attrs(id=self.month_field % id_)
       
    56         select_html = Select(choices=month_choices).render(self.month_field % name, month_val, local_attrs)
       
    57         output.append(select_html)
       
    58 
       
    59         day_choices = [(i, i) for i in range(1, 32)]
       
    60         local_attrs['id'] = self.day_field % id_
       
    61         select_html = Select(choices=day_choices).render(self.day_field % name, day_val, local_attrs)
       
    62         output.append(select_html)
       
    63 
       
    64         year_choices = [(i, i) for i in self.years]
       
    65         local_attrs['id'] = self.year_field % id_
       
    66         select_html = Select(choices=year_choices).render(self.year_field % name, year_val, local_attrs)
       
    67         output.append(select_html)
       
    68 
       
    69         return mark_safe(u'\n'.join(output))
       
    70 
       
    71     def id_for_label(self, id_):
       
    72         return '%s_month' % id_
       
    73     id_for_label = classmethod(id_for_label)
       
    74 
       
    75     def value_from_datadict(self, data, files, name):
       
    76         y, m, d = data.get(self.year_field % name), data.get(self.month_field % name), data.get(self.day_field % name)
       
    77         if y and m and d:
       
    78             return '%s-%s-%s' % (y, m, d)
       
    79         return data.get(name, None)