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