Fixed #13032 - Added localize parameter to form fields to be able to selectively enable localization.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@12867 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Jannis Leidel 2010-03-27 16:43:27 +00:00
parent ad5afd6ed2
commit ca4c6f65ea
7 changed files with 60 additions and 19 deletions

View File

@ -71,7 +71,7 @@ class Field(object):
def __init__(self, required=True, widget=None, label=None, initial=None,
help_text=None, error_messages=None, show_hidden_initial=False,
validators=[]):
validators=[], localize=False):
# required -- Boolean that specifies whether the field is required.
# True by default.
# widget -- A Widget class, or instance of a Widget class, that should
@ -85,9 +85,12 @@ class Field(object):
# initial -- A value to use in this Field's initial display. This value
# is *not* used as a fallback if data isn't given.
# help_text -- An optional string to use as "help text" for this Field.
# error_messages -- An optional dictionary to override the default
# messages that the field will raise.
# show_hidden_initial -- Boolean that specifies if it is needed to render a
# hidden widget with initial value after widget.
# validators -- List of addtional validators to use
# localize -- Boolean that specifies if the field should be localized.
if label is not None:
label = smart_unicode(label)
self.required, self.label, self.initial = required, label, initial
@ -100,6 +103,9 @@ class Field(object):
if isinstance(widget, type):
widget = widget()
# Trigger the localization machinery if needed.
self.localize = localize
# Hook into self.widget_attrs() for any Field-specific HTML attributes.
extra_attrs = self.widget_attrs(widget)
if extra_attrs:
@ -119,6 +125,9 @@ class Field(object):
self.validators = self.default_validators + validators
def localize_value(self, value):
return formats.localize_input(value)
def to_python(self, value):
return value
@ -213,7 +222,8 @@ class IntegerField(Field):
value = super(IntegerField, self).to_python(value)
if value in validators.EMPTY_VALUES:
return None
value = formats.sanitize_separators(value)
if self.localize:
value = formats.sanitize_separators(value)
try:
value = int(str(value))
except (ValueError, TypeError):
@ -233,7 +243,8 @@ class FloatField(IntegerField):
value = super(IntegerField, self).to_python(value)
if value in validators.EMPTY_VALUES:
return None
value = formats.sanitize_separators(value)
if self.localize:
value = formats.sanitize_separators(value)
try:
value = float(value)
except (ValueError, TypeError):
@ -268,7 +279,8 @@ class DecimalField(Field):
"""
if value in validators.EMPTY_VALUES:
return None
value = formats.sanitize_separators(value)
if self.localize:
value = formats.sanitize_separators(value)
value = smart_str(value).strip()
try:
value = Decimal(value)

View File

@ -443,6 +443,8 @@ class BoundField(StrAndUnicode):
name = self.html_name
else:
name = self.html_initial_name
if self.field.localize:
data = self.field.localize_value(data)
return widget.render(name, data, attrs=attrs)
def as_text(self, attrs=None, **kwargs):

View File

@ -13,7 +13,6 @@ from django.utils.safestring import mark_safe
from django.utils import formats
import time
import datetime
from django.utils.formats import get_format
from util import flatatt
from urlparse import urljoin
@ -214,7 +213,7 @@ class Input(Widget):
final_attrs = self.build_attrs(attrs, type=self.input_type, name=name)
if value != '':
# Only add the 'value' attribute if a value is non-empty.
final_attrs['value'] = force_unicode(formats.localize_input(value))
final_attrs['value'] = force_unicode(value)
return mark_safe(u'<input%s />' % flatatt(final_attrs))
class TextInput(Input):
@ -319,7 +318,7 @@ class DateInput(Input):
# formatted by HiddenInput using formats.localize_input, which is not
# necessarily the format used for this widget. Attempt to convert it.
try:
input_format = get_format('DATE_INPUT_FORMATS')[0]
input_format = formats.get_format('DATE_INPUT_FORMATS')[0]
initial = datetime.date(*time.strptime(initial, input_format)[:3])
except (TypeError, ValueError):
pass
@ -350,7 +349,7 @@ class DateTimeInput(Input):
# formatted by HiddenInput using formats.localize_input, which is not
# necessarily the format used for this widget. Attempt to convert it.
try:
input_format = get_format('DATETIME_INPUT_FORMATS')[0]
input_format = formats.get_format('DATETIME_INPUT_FORMATS')[0]
initial = datetime.datetime(*time.strptime(initial, input_format)[:6])
except (TypeError, ValueError):
pass
@ -381,7 +380,7 @@ class TimeInput(Input):
# formatted by HiddenInput using formats.localize_input, which is not
# necessarily the format used for this widget. Attempt to convert it.
try:
input_format = get_format('TIME_INPUT_FORMATS')[0]
input_format = formats.get_format('TIME_INPUT_FORMATS')[0]
initial = datetime.time(*time.strptime(initial, input_format)[3:6])
except (TypeError, ValueError):
pass
@ -771,6 +770,8 @@ class SplitHiddenDateTimeWidget(SplitDateTimeWidget):
"""
is_hidden = True
def __init__(self, attrs=None):
widgets = (HiddenInput(attrs=attrs), HiddenInput(attrs=attrs))
super(SplitDateTimeWidget, self).__init__(widgets, attrs)
def __init__(self, attrs=None, date_format=None, time_format=None):
super(SplitHiddenDateTimeWidget, self).__init__(attrs, date_format, time_format)
for widget in self.widgets:
widget.input_type = 'hidden'
widget.is_hidden = True

View File

@ -259,6 +259,7 @@ error message keys it uses.
``validators``
~~~~~~~~~~~~~~
.. versionadded:: 1.2
.. attribute:: Field.validators
@ -268,6 +269,20 @@ for this field.
See the :ref:`validators documentation <ref-validators>` for more information.
``localize``
~~~~~~~~~~~~
.. versionadded:: 1.2
.. attribute:: Field.localize
The ``localize`` argument enables the localization of form data, input as well
as the rendered output.
See the :ref:`format localization <format-localization>` documentation for
more information.
Built-in ``Field`` classes
--------------------------

View File

@ -268,6 +268,13 @@ Django uses different formats for different locales when guessing the format
used by the user when inputting data on forms. Note that Django uses different
formats for displaying data, and for parsing it.
To enable a form field to localize input and output data simply use its
``localize`` argument::
class CashRegisterForm(forms.Form):
product = forms.CharField()
revenue = forms.DecimalField(max_digits=4, decimal_places=2, localize=True)
Creating custom format files
----------------------------

View File

@ -3,16 +3,19 @@ from django.forms.extras import SelectDateWidget
from models import Company
class I18nForm(forms.Form):
decimal_field = forms.DecimalField()
float_field = forms.FloatField()
date_field = forms.DateField()
datetime_field = forms.DateTimeField()
time_field = forms.TimeField()
integer_field = forms.IntegerField()
decimal_field = forms.DecimalField(localize=True)
float_field = forms.FloatField(localize=True)
date_field = forms.DateField(localize=True)
datetime_field = forms.DateTimeField(localize=True)
time_field = forms.TimeField(localize=True)
integer_field = forms.IntegerField(localize=True)
class SelectDateForm(forms.Form):
date_field = forms.DateField(widget=SelectDateWidget)
class CompanyForm(forms.ModelForm):
cents_payed = forms.DecimalField(max_digits=4, decimal_places=2, localize=True)
products_delivered = forms.IntegerField(localize=True)
class Meta:
model = Company

View File

@ -409,7 +409,8 @@ class FormattingTests(TestCase):
self.assertEqual(localize_input(datetime.datetime(2009, 12, 31, 6, 0, 0)), '31.12.2009 06:00:00')
self.assertEqual(datetime.datetime(2009, 12, 31, 6, 0, 0), form6.cleaned_data['date_added'])
settings.USE_THOUSAND_SEPARATOR = True
self.assert_(u'12.000' in form6.as_ul())
# Checking for the localized "products_delivered" field
self.assert_(u'<input type="text" name="products_delivered" value="12.000" id="id_products_delivered" />' in form6.as_ul())
finally:
deactivate()