Code

Ticket #12986: 12986-3.diff

File 12986-3.diff, 5.1 KB (added by bmihelac, 4 years ago)
Line 
1Index: ../django/forms/extras/widgets.py
2===================================================================
3--- ../django/forms/extras/widgets.py   (revision 12776)
4+++ ../django/forms/extras/widgets.py   (working copy)
5@@ -13,14 +13,15 @@
6 
7 __all__ = ('SelectDateWidget',)
8 
9-RE_DATE = re.compile(r'(\d{4})-(\d\d?)-(\d\d?)$')
10-
11 class SelectDateWidget(Widget):
12     """
13     A Widget that splits date input into three <select> boxes.
14 
15     This also serves as an example of a Widget that has more than one HTML
16     element and hence implements value_from_datadict.
17+   
18+    If format localization is used (USE_L10N = True), combination of %Y, %m and %d directives in default
19+    input format is needed for invalid dates to be rendered.
20     """
21     none_value = (0, '---')
22     month_field = '%s_month'
23@@ -36,17 +37,31 @@
24         else:
25             this_year = datetime.date.today().year
26             self.years = range(this_year, this_year+10)
27-
28+           
29     def render(self, name, value, attrs=None):
30         try:
31             year_val, month_val, day_val = value.year, value.month, value.day
32         except AttributeError:
33             year_val = month_val = day_val = None
34             if isinstance(value, basestring):
35-                match = RE_DATE.match(value)
36-                if match:
37-                    year_val, month_val, day_val = [int(v) for v in match.groups()]
38-
39+                input_format = get_format('DATE_INPUT_FORMATS')[0]
40+                try:
41+                    val = datetime.datetime.strptime(value, input_format)
42+                    year_val, month_val, day_val = val.year, val.month, val.day
43+                except ValueError:
44+                    # When selected day is invalid in month convert input format to regex and receive year, day, month values
45+                    # so the failed date still can be rendered.
46+                    format_to_re_dic = {
47+                       '%Y': r'(?P<y>\d+)?',
48+                       '%m': r'(?P<m>\d+?)?',
49+                       '%d': r'(?P<d>\d+?)?'
50+                    }
51+                    re_str = input_format
52+                    for k, v in format_to_re_dic.iteritems():
53+                       re_str = re_str.replace(k, v)                 
54+                    match = re.match('^' + re_str + '$', value)
55+                    if match:
56+                        year_val, month_val, day_val = int(match.group('y')), int(match.group('m')), int(match.group('d'))
57         choices = [(i, i) for i in self.years]
58         year_html = self.create_select(name, self.year_field, value, year_val, choices)
59         choices = MONTHS.items()
60@@ -81,16 +96,8 @@
61         if y == m == d == "0":
62             return None
63         if y and m and d:
64-            if settings.USE_L10N:
65-                input_format = get_format('DATE_INPUT_FORMATS')[0]
66-                try:
67-                    date_value = datetime.date(int(y), int(m), int(d))
68-                except ValueError:
69-                    pass
70-                else:
71-                    return date_value.strftime(input_format)
72-            else:
73-                return '%s-%s-%s' % (y, m, d)
74+            input_format = get_format('DATE_INPUT_FORMATS')[0]
75+            return input_format.replace('%Y', y).replace('%m', m).replace('%d', d)
76         return data.get(name, None)
77 
78     def create_select(self, name, field, value, val, choices):
79@@ -98,8 +105,7 @@
80             id_ = self.attrs['id']
81         else:
82             id_ = 'id_%s' % name
83-        if not (self.required and value):
84-            choices.insert(0, self.none_value)
85+        choices.insert(0, self.none_value)
86         local_attrs = self.build_attrs(id=field % id_)
87         s = Select(choices=choices)
88         select_html = s.render(field % name, val, local_attrs)
89Index: ../tests/regressiontests/forms/extra.py
90===================================================================
91--- ../tests/regressiontests/forms/extra.py     (revision 12776)
92+++ ../tests/regressiontests/forms/extra.py     (working copy)
93@@ -364,6 +364,32 @@
94 2008-04-01
95 
96 
97+USE_L10N tests
98+
99+>>> from django.utils import  translation
100+>>> translation.activate('nl')
101+>>> from django.conf import settings
102+>>> settings.USE_L10N=True
103+>>> w.value_from_datadict({'date_year': '2010', 'date_month': '8', 'date_day': '13'}, {}, 'date')
104+'13-8-2010'
105+>>> res = w.render('date', '13-08-2010')
106+>>> u'<option value="13" selected="selected">13</option>' in res
107+True
108+>>> u'<option value="2010" selected="selected">2010</option>' in res
109+True
110+>>> u'<option value="8" selected="selected">augustus</option>' in res
111+True
112+>>> w.value_from_datadict({'date_year': '2010', 'date_month': '8', 'date_day': '13'}, {}, 'date')
113+'13-8-2010'
114+>>> res = w.render('date', '31-2-2010')
115+>>> u'<option value="31" selected="selected">31</option>' in res
116+True
117+>>> u'<option value="2010" selected="selected">2010</option>' in res
118+True
119+>>> u'<option value="2" selected="selected">februari</option>' in res
120+True
121+>>> translation.deactivate()
122+
123 # MultiWidget and MultiValueField #############################################
124 # MultiWidgets are widgets composed of other widgets. They are usually
125 # combined with MultiValueFields - a field that is composed of other fields.