Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #13560 -- Fixed localization of widgets.

Particularly this fixes the SplitDateTimeField and the AdminDateWidget by localizating the widget's value in its render method instead of the form field. Thanks to David Danier for the report and Russell for help with the patch.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@13296 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit b057a8b247d14328f058b8bc89da0519516ced82 1 parent 8a6cb3d
Jannis Leidel authored May 21, 2010
2  django/contrib/admin/widgets.py
@@ -44,7 +44,7 @@ def render(self, name, value, attrs=None, choices=()):
44 44
             (name, self.verbose_name.replace('"', '\\"'), int(self.is_stacked), settings.ADMIN_MEDIA_PREFIX))
45 45
         return mark_safe(u''.join(output))
46 46
 
47  
-class AdminDateWidget(forms.DateTimeInput):
  47
+class AdminDateWidget(forms.DateInput):
48 48
     class Media:
49 49
         js = (settings.ADMIN_MEDIA_PREFIX + "js/calendar.js",
50 50
               settings.ADMIN_MEDIA_PREFIX + "js/admin/DateTimeShortcuts.js")
14  django/forms/fields.py
@@ -105,6 +105,8 @@ def __init__(self, required=True, widget=None, label=None, initial=None,
105 105
 
106 106
         # Trigger the localization machinery if needed.
107 107
         self.localize = localize
  108
+        if self.localize:
  109
+            widget.is_localized = True
108 110
 
109 111
         # Hook into self.widget_attrs() for any Field-specific HTML attributes.
110 112
         extra_attrs = self.widget_attrs(widget)
@@ -125,9 +127,6 @@ def __init__(self, required=True, widget=None, label=None, initial=None,
125 127
 
126 128
         self.validators = self.default_validators + validators
127 129
 
128  
-    def localize_value(self, value):
129  
-        return formats.localize_input(value)
130  
-
131 130
     def to_python(self, value):
132 131
         return value
133 132
 
@@ -843,9 +842,14 @@ def __init__(self, input_date_formats=None, input_time_formats=None, *args, **kw
843 842
         errors = self.default_error_messages.copy()
844 843
         if 'error_messages' in kwargs:
845 844
             errors.update(kwargs['error_messages'])
  845
+        localize = kwargs.get('localize', False)
846 846
         fields = (
847  
-            DateField(input_formats=input_date_formats, error_messages={'invalid': errors['invalid_date']}),
848  
-            TimeField(input_formats=input_time_formats, error_messages={'invalid': errors['invalid_time']}),
  847
+            DateField(input_formats=input_date_formats,
  848
+                      error_messages={'invalid': errors['invalid_date']},
  849
+                      localize=localize),
  850
+            TimeField(input_formats=input_time_formats,
  851
+                      error_messages={'invalid': errors['invalid_time']},
  852
+                      localize=localize),
849 853
         )
850 854
         super(SplitDateTimeField, self).__init__(fields, *args, **kwargs)
851 855
 
2  django/forms/forms.py
@@ -443,8 +443,6 @@ def as_widget(self, widget=None, attrs=None, only_initial=False):
443 443
             name = self.html_name
444 444
         else:
445 445
             name = self.html_initial_name
446  
-        if self.field.localize:
447  
-            data = self.field.localize_value(data)
448 446
         return widget.render(name, data, attrs=attrs)
449 447
 
450 448
     def as_text(self, attrs=None, **kwargs):
54  django/forms/widgets.py
@@ -10,7 +10,7 @@
10 10
 from django.utils.translation import ugettext
11 11
 from django.utils.encoding import StrAndUnicode, force_unicode
12 12
 from django.utils.safestring import mark_safe
13  
-from django.utils import formats
  13
+from django.utils import datetime_safe, formats
14 14
 import time
15 15
 import datetime
16 16
 from util import flatatt
@@ -133,6 +133,7 @@ class Widget(object):
133 133
     __metaclass__ = MediaDefiningClass
134 134
     is_hidden = False          # Determines whether this corresponds to an <input type="hidden">.
135 135
     needs_multipart_form = False # Determines does this widget need multipart-encrypted form
  136
+    is_localized = False
136 137
 
137 138
     def __init__(self, attrs=None):
138 139
         if attrs is not None:
@@ -208,12 +209,18 @@ class Input(Widget):
208 209
     """
209 210
     input_type = None # Subclasses must define this.
210 211
 
  212
+    def _format_value(self, value):
  213
+        if self.is_localized:
  214
+            return formats.localize_input(value)
  215
+        return value
  216
+
211 217
     def render(self, name, value, attrs=None):
212  
-        if value is None: value = ''
  218
+        if value is None:
  219
+            value = ''
213 220
         final_attrs = self.build_attrs(attrs, type=self.input_type, name=name)
214 221
         if value != '':
215 222
             # Only add the 'value' attribute if a value is non-empty.
216  
-            final_attrs['value'] = force_unicode(value)
  223
+            final_attrs['value'] = force_unicode(self._format_value(value))
217 224
         return mark_safe(u'<input%s />' % flatatt(final_attrs))
218 225
 
219 226
 class TextInput(Input):
@@ -295,7 +302,7 @@ def render(self, name, value, attrs=None):
295 302
 
296 303
 class DateInput(Input):
297 304
     input_type = 'text'
298  
-    format = None
  305
+    format = '%Y-%m-%d'     # '2006-10-25'
299 306
 
300 307
     def __init__(self, attrs=None, format=None):
301 308
         super(DateInput, self).__init__(attrs)
@@ -303,16 +310,13 @@ def __init__(self, attrs=None, format=None):
303 310
             self.format = format
304 311
 
305 312
     def _format_value(self, value):
306  
-        if value is None:
307  
-            return ''
  313
+        if self.is_localized:
  314
+            return formats.localize_input(value)
308 315
         elif hasattr(value, 'strftime'):
309  
-            return formats.localize_input(value, self.format)
  316
+            value = datetime_safe.new_date(value)
  317
+            return value.strftime(self.format)
310 318
         return value
311 319
 
312  
-    def render(self, name, value, attrs=None):
313  
-        value = self._format_value(value)
314  
-        return super(DateInput, self).render(name, value, attrs)
315  
-
316 320
     def _has_changed(self, initial, data):
317 321
         # If our field has show_hidden_initial=True, initial will be a string
318 322
         # formatted by HiddenInput using formats.localize_input, which is not
@@ -326,7 +330,7 @@ def _has_changed(self, initial, data):
326 330
 
327 331
 class DateTimeInput(Input):
328 332
     input_type = 'text'
329  
-    format = None
  333
+    format = '%Y-%m-%d %H:%M:%S'     # '2006-10-25 14:30:59'
330 334
 
331 335
     def __init__(self, attrs=None, format=None):
332 336
         super(DateTimeInput, self).__init__(attrs)
@@ -334,16 +338,13 @@ def __init__(self, attrs=None, format=None):
334 338
             self.format = format
335 339
 
336 340
     def _format_value(self, value):
337  
-        if value is None:
338  
-            return ''
  341
+        if self.is_localized:
  342
+            return formats.localize_input(value)
339 343
         elif hasattr(value, 'strftime'):
340  
-            return formats.localize_input(value, self.format)
  344
+            value = datetime_safe.new_datetime(value)
  345
+            return value.strftime(self.format)
341 346
         return value
342 347
 
343  
-    def render(self, name, value, attrs=None):
344  
-        value = self._format_value(value)
345  
-        return super(DateTimeInput, self).render(name, value, attrs)
346  
-
347 348
     def _has_changed(self, initial, data):
348 349
         # If our field has show_hidden_initial=True, initial will be a string
349 350
         # formatted by HiddenInput using formats.localize_input, which is not
@@ -357,7 +358,7 @@ def _has_changed(self, initial, data):
357 358
 
358 359
 class TimeInput(Input):
359 360
     input_type = 'text'
360  
-    format = None
  361
+    format = '%H:%M:%S'     # '14:30:59'
361 362
 
362 363
     def __init__(self, attrs=None, format=None):
363 364
         super(TimeInput, self).__init__(attrs)
@@ -365,16 +366,12 @@ def __init__(self, attrs=None, format=None):
365 366
             self.format = format
366 367
 
367 368
     def _format_value(self, value):
368  
-        if value is None:
369  
-            return ''
  369
+        if self.is_localized:
  370
+            return formats.localize_input(value)
370 371
         elif hasattr(value, 'strftime'):
371  
-            return formats.localize_input(value, self.format)
  372
+            return value.strftime(self.format)
372 373
         return value
373 374
 
374  
-    def render(self, name, value, attrs=None):
375  
-        value = self._format_value(value)
376  
-        return super(TimeInput, self).render(name, value, attrs)
377  
-
378 375
     def _has_changed(self, initial, data):
379 376
         # If our field has show_hidden_initial=True, initial will be a string
380 377
         # formatted by HiddenInput using formats.localize_input, which is not
@@ -674,6 +671,9 @@ def __init__(self, widgets, attrs=None):
674 671
         super(MultiWidget, self).__init__(attrs)
675 672
 
676 673
     def render(self, name, value, attrs=None):
  674
+        if self.is_localized:
  675
+            for widget in self.widgets:
  676
+                widget.is_localized = self.is_localized
677 677
         # value is a list of values, each corresponding to a widget
678 678
         # in self.widgets.
679 679
         if not isinstance(value, list):
1  tests/regressiontests/admin_widgets/models.py
@@ -105,6 +105,7 @@ class CarTire(models.Model):
105 105
 <p class="datetime">Date: <input value="2007-12-01" type="text" class="vDateField" name="test_0" size="10" /><br />Time: <input value="09:30:00" type="text" class="vTimeField" name="test_1" size="8" /></p>
106 106
 >>> activate('de-at')
107 107
 >>> settings.USE_L10N = True
  108
+>>> w.is_localized = True
108 109
 >>> print conditional_escape(w.render('test', datetime(2007, 12, 1, 9, 30)))
109 110
 <p class="datetime">Datum: <input value="01.12.2007" type="text" class="vDateField" name="test_0" size="10" /><br />Zeit: <input value="09:30:00" type="text" class="vTimeField" name="test_1" size="8" /></p>
110 111
 >>> deactivate()
4  tests/regressiontests/forms/widgets.py
@@ -1135,6 +1135,7 @@
1135 1135
 u'<input type="text" name="date" value="2007-09-17 12:51:00" />'
1136 1136
 >>> activate('de-at')
1137 1137
 >>> settings.USE_L10N = True
  1138
+>>> w.is_localized = True
1138 1139
 >>> w.render('date', d)
1139 1140
 u'<input type="text" name="date" value="17.09.2007 12:51:34" />'
1140 1141
 >>> deactivate()
@@ -1176,6 +1177,7 @@
1176 1177
 
1177 1178
 >>> activate('de-at')
1178 1179
 >>> settings.USE_L10N = True
  1180
+>>> w.is_localized = True
1179 1181
 >>> w.render('date', d)
1180 1182
 u'<input type="text" name="date" value="17.09.2007" />'
1181 1183
 >>> deactivate()
@@ -1220,6 +1222,7 @@
1220 1222
 
1221 1223
 >>> activate('de-at')
1222 1224
 >>> settings.USE_L10N = True
  1225
+>>> w.is_localized = True
1223 1226
 >>> w.render('date', d)
1224 1227
 u'<input type="text" name="date" value="17.09.2007" />'
1225 1228
 >>> deactivate()
@@ -1259,6 +1262,7 @@
1259 1262
 u'<input type="hidden" name="date_0" value="2007-09-17" /><input type="hidden" name="date_1" value="12:51:00" />'
1260 1263
 >>> activate('de-at')
1261 1264
 >>> settings.USE_L10N = True
  1265
+>>> w.is_localized = True
1262 1266
 >>> w.render('date', datetime.datetime(2007, 9, 17, 12, 51))
1263 1267
 u'<input type="hidden" name="date_0" value="17.09.2007" /><input type="hidden" name="date_1" value="12:51:00" />'
1264 1268
 >>> deactivate()
1  tests/regressiontests/i18n/forms.py
@@ -16,6 +16,7 @@ class SelectDateForm(forms.Form):
16 16
 class CompanyForm(forms.ModelForm):
17 17
     cents_payed = forms.DecimalField(max_digits=4, decimal_places=2, localize=True)
18 18
     products_delivered = forms.IntegerField(localize=True)
  19
+    date_added = forms.DateTimeField(localize=True)
19 20
 
20 21
     class Meta:
21 22
         model = Company

0 notes on commit b057a8b

Please sign in to comment.
Something went wrong with that request. Please try again.