web/lib/django/forms/extras/widgets.py
changeset 38 77b6da96e6f1
equal deleted inserted replaced
37:8d941af65caf 38:77b6da96e6f1
       
     1 """
       
     2 Extra HTML Widget classes
       
     3 """
       
     4 
       
     5 import time
       
     6 import datetime
       
     7 import re
       
     8 
       
     9 from django.forms.widgets import Widget, Select
       
    10 from django.utils import datetime_safe
       
    11 from django.utils.dates import MONTHS
       
    12 from django.utils.safestring import mark_safe
       
    13 from django.utils.formats import get_format
       
    14 from django.conf import settings
       
    15 
       
    16 __all__ = ('SelectDateWidget',)
       
    17 
       
    18 RE_DATE = re.compile(r'(\d{4})-(\d\d?)-(\d\d?)$')
       
    19 
       
    20 class SelectDateWidget(Widget):
       
    21     """
       
    22     A Widget that splits date input into three <select> boxes.
       
    23 
       
    24     This also serves as an example of a Widget that has more than one HTML
       
    25     element and hence implements value_from_datadict.
       
    26     """
       
    27     none_value = (0, '---')
       
    28     month_field = '%s_month'
       
    29     day_field = '%s_day'
       
    30     year_field = '%s_year'
       
    31 
       
    32     def __init__(self, attrs=None, years=None, required=True):
       
    33         # years is an optional list/tuple of years to use in the "year" select box.
       
    34         self.attrs = attrs or {}
       
    35         self.required = required
       
    36         if years:
       
    37             self.years = years
       
    38         else:
       
    39             this_year = datetime.date.today().year
       
    40             self.years = range(this_year, this_year+10)
       
    41 
       
    42     def render(self, name, value, attrs=None):
       
    43         try:
       
    44             year_val, month_val, day_val = value.year, value.month, value.day
       
    45         except AttributeError:
       
    46             year_val = month_val = day_val = None
       
    47             if isinstance(value, basestring):
       
    48                 if settings.USE_L10N:
       
    49                     try:
       
    50                         input_format = get_format('DATE_INPUT_FORMATS')[0]
       
    51                         # Python 2.4 compatibility:
       
    52                         #     v = datetime.datetime.strptime(value, input_format)
       
    53                         # would be clearer, but datetime.strptime was added in 
       
    54                         # Python 2.5
       
    55                         v = datetime.datetime(*(time.strptime(value, input_format)[0:6]))
       
    56                         year_val, month_val, day_val = v.year, v.month, v.day
       
    57                     except ValueError:
       
    58                         pass
       
    59                 else:
       
    60                     match = RE_DATE.match(value)
       
    61                     if match:
       
    62                         year_val, month_val, day_val = [int(v) for v in match.groups()]
       
    63         choices = [(i, i) for i in self.years]
       
    64         year_html = self.create_select(name, self.year_field, value, year_val, choices)
       
    65         choices = MONTHS.items()
       
    66         month_html = self.create_select(name, self.month_field, value, month_val, choices)
       
    67         choices = [(i, i) for i in range(1, 32)]
       
    68         day_html = self.create_select(name, self.day_field, value, day_val,  choices)
       
    69 
       
    70         format = get_format('DATE_FORMAT')
       
    71         escaped = False
       
    72         output = []
       
    73         for char in format:
       
    74             if escaped:
       
    75                 escaped = False
       
    76             elif char == '\\':
       
    77                 escaped = True
       
    78             elif char in 'Yy':
       
    79                 output.append(year_html)
       
    80             elif char in 'bFMmNn':
       
    81                 output.append(month_html)
       
    82             elif char in 'dj':
       
    83                 output.append(day_html)
       
    84         return mark_safe(u'\n'.join(output))
       
    85 
       
    86     def id_for_label(self, id_):
       
    87         return '%s_month' % id_
       
    88     id_for_label = classmethod(id_for_label)
       
    89 
       
    90     def value_from_datadict(self, data, files, name):
       
    91         y = data.get(self.year_field % name)
       
    92         m = data.get(self.month_field % name)
       
    93         d = data.get(self.day_field % name)
       
    94         if y == m == d == "0":
       
    95             return None
       
    96         if y and m and d:
       
    97             if settings.USE_L10N:
       
    98                 input_format = get_format('DATE_INPUT_FORMATS')[0]
       
    99                 try:
       
   100                     date_value = datetime.date(int(y), int(m), int(d))
       
   101                 except ValueError:
       
   102                     pass
       
   103                 else:
       
   104                     date_value = datetime_safe.new_date(date_value)
       
   105                     return date_value.strftime(input_format)
       
   106             else:
       
   107                 return '%s-%s-%s' % (y, m, d)
       
   108         return data.get(name, None)
       
   109 
       
   110     def create_select(self, name, field, value, val, choices):
       
   111         if 'id' in self.attrs:
       
   112             id_ = self.attrs['id']
       
   113         else:
       
   114             id_ = 'id_%s' % name
       
   115         if not (self.required and val):
       
   116             choices.insert(0, self.none_value)
       
   117         local_attrs = self.build_attrs(id=field % id_)
       
   118         s = Select(choices=choices)
       
   119         select_html = s.render(field % name, val, local_attrs)
       
   120         return select_html
       
   121