8000 Fixed #13560 -- Fixed localization of widgets. · ddriddle/django@b057a8b · GitHub
[go: up one dir, main page]

Skip to content

Commit b057a8b

Browse files
committed
Fixed django#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
1 parent 8a6cb3d commit b057a8b

File tree

7 files changed

+43
-35
lines changed

7 files changed

+43
-35
lines changed

django/contrib/admin/widgets.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def render(self, name, value, attrs=None, choices=()):
4444
(name, self.verbose_name.replace('"', '\\"'), int(self.is_stacked), settings.ADMIN_MEDIA_PREFIX))
4545
return mark_safe(u''.join(output))
4646

47-
class AdminDateWidget(forms.DateTimeInput):
47+
class AdminDateWidget(forms.DateInput):
4848
class Media:
4949
js = (settings.ADMIN_MEDIA_PREFIX + "js/calendar.js",
5050
settings.ADMIN_MEDIA_PREFIX + "js/admin/DateTimeShortcuts.js")

django/forms/fields.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ def __init__(self, required=True, widget=None, label=None, initial=None,
105105

106106
# Trigger the localization machinery if needed.
107107
self.localize = localize
108+
if self.localize:
109+
widget.is_localized = True
108110

109111
# Hook into self.widget_attrs() for any Field-specific HTML attributes.
110112
extra_attrs = self.widget_attrs(widget)
@@ -125,9 +127,6 @@ def __init__(self, required=True, widget=None, label=None, initial=None,
125127

126128
self.validators = self.default_validators + validators
127129

128-
def localize_value(self, value):
129-
return formats.localize_input(value)
130-
131130
def to_python(self, value):
132131
return value
133132

@@ -843,9 +842,14 @@ def __init__(self, input_date_formats=None, input_time_formats=None, *args, **kw
843842
errors = self.default_error_messages.copy()
844843
if 'error_messages' in kwargs:
845844
errors.update(kwargs['error_messages'])
845+
localize = kwargs.get('localize', False)
846846
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),
849853
)
850854
super(SplitDateTimeField, self).__init__(fields, *args, **kwargs)
851855

django/forms/forms.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -443,8 +443,6 @@ def as_widget(self, widget=None, attrs=None, only_initial=False):
443443
name = self.html_name
444444
else:
445445
name = self.html_initial_name
446-
if self.field.localize:
447-
data = self.field.localize_value(data)
448446
return widget.render(name, data, attrs=attrs)
449447

450448
def as_text(self, attrs=None, **kwargs):

django/forms/widgets.py

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from django.utils.translation import ugettext
1111
from django.utils.encoding import StrAndUnicode, force_unicode
1212
from django.utils.safestring import mark_safe
13-
from django.utils import formats
13+
from django.utils import datetime_safe, formats
1414
import time
1515
import datetime
1616
from util import flatatt
@@ -133,6 +133,7 @@ class Widget(object):
133133
__metaclass__ = MediaDefiningClass
134134
is_hidden = False # Determines whether this corresponds to an <input type="hidden">.
135135
needs_multipart_form = False # Determines does this widget need multipart-encrypted form
136+
is_localized = False
136137

137138
def __init__(self, attrs=None):
138139
if attrs is not None:
@@ -208,12 +209,18 @@ class Input(Widget):
208209
"""
209210
input_type = None # Subclasses must define this.
210211

212+
def _format_value(self, value):
213+
if self.is_localized:
214+
return formats.localize_input(value)
215+
return value
216+
211217
def render(self, name, value, attrs=None):
212-
if value is None: value = ''
218+
if value is None:
219+
value = ''
213220
final_attrs = self.build_attrs(attrs, type=self.input_type, name=name)
214221
if value != '':
215222
# 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))
217224
return mark_safe(u'<input%s />' % flatatt(final_attrs))
218225

219226
class TextInput(Input):
@@ -295,24 +302,21 @@ def render(self, name, value, attrs=None):
295302

296303
class DateInput(Input):
297304
input_type = 'text'
298-
format = None
305+
format = '%Y-%m-%d' # '2006-10-25'
299306

300307
def __init__(self, attrs=None, format=None):
301308
super(DateInput, self).__init__(attrs)
302309
if format:
303310
self.format = format
304311

305312
def _format_value(self, value):
306-
if value is None:
307-
return ''
313+
if self.is_localized:
314+
return formats.localize_input(value)
308315
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)
310318
return value
311319

312-
def render(self, name, value, attrs=None):
313-
value = self._format_value(value)
314-
return super(DateInput, self).render(name, value, attrs)
315-
316320
def _has_changed(self, initial, data):
317321
# If our field has show_hidden_initial=True, initial will be a string
318322
# formatted by HiddenInput using formats.localize_input, which is not
@@ -326,24 +330,21 @@ def _has_changed(self, initial, data):
326330

327331
class DateTimeInput(Input):
328332
input_type = 'text'
329-
format = None
333+
format = '%Y-%m-%d %H:%M:%S' # '2006-10-25 14:30:59'
330334

331335
def __init__(self, attrs=None, format=None):
332336
super(DateTimeInput, self).__init__(attrs)
333337
if format:
334338
self.format = format
335339

336340
def _format_value(self, value):
337-
if value is None:
338-
return ''
341+
if self.is_localized:
342+
return formats.localize_input(value)
339343
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)
341346
return value
342347

343-
def render(self, name, value, attrs=None):
344-
value = self._format_value(value)
345-
return super(DateTimeInput, self).render(name, value, attrs)
346-
347348
def _has_changed(self, initial, data):
348349
# If our field has show_hidden_initial=True, initial will be a string
349350
# formatted by HiddenInput using formats.localize_input, which is not
@@ -357,24 +358,20 @@ def _has_changed(self, initial, data):
357358

358359
class TimeInput(Input):
359360
input_type = 'text'
360-
format = None
361+
format = '%H:%M:%S' # '14:30:59'
361362

362363
def __init__(self, attrs=None, format=None):
363364
super(TimeInput, self).__init__(attrs)
364365
if format:
365366
self.format = format
366367

367368
def _format_value(self, value):
368-
if value is None:
369-
return ''
369+
if self.is_localized:
370+
return formats.localize_input(value)
370371
elif hasattr(value, 'strftime'):
371-
return formats.localize_input(value, self.format)
372+
return value.strftime(self.format)
372373
return value
373374

374-
def render(self, name, value, attrs=None):
375-
value = self._format_value(value)
376-
return super(TimeInput, self).render(name, value, attrs)
377-
378375
def _has_changed(self, initial, data):
379376
# If our field has show_hidden_initial=True, initial will be a string
380377
# formatted by HiddenInput using formats.localize_input, which is not
@@ -674,6 +671,9 @@ def __init__(self, widgets, attrs=None):
674671
super(MultiWidget, self).__init__(attrs)
675672

676673
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
677677
# value is a list of values, each corresponding to a widget
678678
# in self.widgets.
679679
if not isinstance(value, list):

tests/regressiontests/admin_widgets/models.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ class CarTire(models.Model):
105105
<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>
106106
>>> activate('de-at')
107107
>>> settings.USE_L10N = True
108+
>>> w.is_localized = True
108109
>>> print conditional_escape(w.render('test', datetime(2007, 12, 1, 9, 30)))
109110
<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>
110111
>>> deactivate()

tests/regressiontests/forms/widgets.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,6 +1135,7 @@
11351135
u'<input type="text" name="date" value="2007-09-17 12:51:00" />'
11361136
>>> activate('de-at')
11371137
>>> settings.USE_L10N = True
1138+
>>> w.is_localized = True
11381139
>>> w.render('date', d)
11391140
u'<input type="text" name="date" value="17.09.2007 12:51:34" />'
11401141
>>> deactivate()
@@ -1176,6 +1177,7 @@
11761177
11771178
>>> activate('de-at')
11781179
>>> settings.USE_L10N = True
1180+
>>> w.is_localized = True
11791181
>>> w.render('date', d)
11801182
u'<input type="text" name="date" value="17.09.2007" />'
11811183
>>> deactivate()
@@ -1220,6 +1222,7 @@
12201222
12211223
>>> activate('de-at')
12221224
>>> settings.USE_L10N = True
1225+
>>> w.is_localized = True
12231226
>>> w.render('date', d)
12241227
u'<input type="text" name="date" value="17.09.2007" />'
12251228
>>> deactivate()
@@ -1259,6 +1262,7 @@
12591262
u'<input type="hidden" name="date_0" value="2007-09-17" /><input type="hidden" name="date_1" value="12:51:00" />'
12601263
>>> activate('de-at')
12611264
>>> settings.USE_L10N = True
1265+
>>> w.is_localized = True
12621266
>>> w.render('date', datetime.datetime(2007, 9, 17, 12, 51))
12631267
u'<input type="hidden" name="date_0" value="17.09.2007" /><input type="hidden" name="date_1" value="12:51:00" />'
12641268
>>> deactivate()

tests/regressiontests/i18n/forms.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ class SelectDateForm(forms.Form):
1616
class CompanyForm(forms.ModelForm):
1717
cents_payed = forms.DecimalField(max_digits=4, decimal_places=2, localize=True)
1818
products_delivered = forms.IntegerField(localize=True)
19+
date_added = forms.DateTimeField(localize=True)
1920

2021
class Meta:
2122
model = Company

0 commit comments

Comments
 (0)
0