Ticket #13032: 13032.2.diff

File 13032.2.diff, 10.0 KB (added by jezdez, 5 years ago)

localize as much as possible in the form field

  • django/forms/fields.py

    diff --git a/django/forms/fields.py b/django/forms/fields.py
    index b31fe80..14152c8 100644
    a b class Field(object): 
    7171
    7272    def __init__(self, required=True, widget=None, label=None, initial=None,
    7373                 help_text=None, error_messages=None, show_hidden_initial=False,
    74                  validators=[]):
     74                 validators=[], localize=False):
    7575        # required -- Boolean that specifies whether the field is required.
    7676        #             True by default.
    7777        # widget -- A Widget class, or instance of a Widget class, that should
    class Field(object): 
    8585        # initial -- A value to use in this Field's initial display. This value
    8686        #            is *not* used as a fallback if data isn't given.
    8787        # help_text -- An optional string to use as "help text" for this Field.
     88        # error_messages -- An optional dictionary to override the default
     89        #                   messages that the field will raise.
    8890        # show_hidden_initial -- Boolean that specifies if it is needed to render a
    8991        #                        hidden widget with initial value after widget.
    9092        # validators -- List of addtional validators to use
     93        # localize -- Boolean that specifies if the field should be localized.
    9194        if label is not None:
    9295            label = smart_unicode(label)
    9396        self.required, self.label, self.initial = required, label, initial
    class Field(object): 
    100103        if isinstance(widget, type):
    101104            widget = widget()
    102105
     106        # Trigger the localization machinery if needed.
     107        self.localize = localize
     108
    103109        # Hook into self.widget_attrs() for any Field-specific HTML attributes.
    104110        extra_attrs = self.widget_attrs(widget)
    105111        if extra_attrs:
    class Field(object): 
    119125
    120126        self.validators = self.default_validators + validators
    121127
     128    def localize_value(self, value):
     129        return formats.localize_input(value)
     130
    122131    def to_python(self, value):
    123132        return value
    124133
    class IntegerField(Field): 
    213222        value = super(IntegerField, self).to_python(value)
    214223        if value in validators.EMPTY_VALUES:
    215224            return None
    216         value = formats.sanitize_separators(value)
     225        if self.localize:
     226            value = formats.sanitize_separators(value)
    217227        try:
    218228            value = int(str(value))
    219229        except (ValueError, TypeError):
    class FloatField(IntegerField): 
    233243        value = super(IntegerField, self).to_python(value)
    234244        if value in validators.EMPTY_VALUES:
    235245            return None
    236         value = formats.sanitize_separators(value)
     246        if self.localize:
     247            value = formats.sanitize_separators(value)
    237248        try:
    238249            value = float(value)
    239250        except (ValueError, TypeError):
    class DecimalField(Field): 
    268279        """
    269280        if value in validators.EMPTY_VALUES:
    270281            return None
    271         value = formats.sanitize_separators(value)
     282        if self.localize:
     283            value = formats.sanitize_separators(value)
    272284        value = smart_str(value).strip()
    273285        try:
    274286            value = Decimal(value)
  • django/forms/forms.py

    diff --git a/django/forms/forms.py b/django/forms/forms.py
    index b3718ef..6076065 100644
    a b class BoundField(StrAndUnicode): 
    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)
    446448        return widget.render(name, data, attrs=attrs)
    447449
    448450    def as_text(self, attrs=None, **kwargs):
  • django/forms/widgets.py

    diff --git a/django/forms/widgets.py b/django/forms/widgets.py
    index 8b4112b..082c11b 100644
    a b from django.utils.safestring import mark_safe 
    1313from django.utils import formats
    1414import time
    1515import datetime
    16 from django.utils.formats import get_format
    1716from util import flatatt
    1817from urlparse import urljoin
    1918
    class Input(Widget): 
    214213        final_attrs = self.build_attrs(attrs, type=self.input_type, name=name)
    215214        if value != '':
    216215            # Only add the 'value' attribute if a value is non-empty.
    217             final_attrs['value'] = force_unicode(formats.localize_input(value))
     216            final_attrs['value'] = force_unicode(value)
    218217        return mark_safe(u'<input%s />' % flatatt(final_attrs))
    219218
    220219class TextInput(Input):
    class DateInput(Input): 
    319318        # formatted by HiddenInput using formats.localize_input, which is not
    320319        # necessarily the format used for this widget. Attempt to convert it.
    321320        try:
    322             input_format = get_format('DATE_INPUT_FORMATS')[0]
     321            input_format = formats.get_format('DATE_INPUT_FORMATS')[0]
    323322            initial = datetime.date(*time.strptime(initial, input_format)[:3])
    324323        except (TypeError, ValueError):
    325324            pass
    class DateTimeInput(Input): 
    350349        # formatted by HiddenInput using formats.localize_input, which is not
    351350        # necessarily the format used for this widget. Attempt to convert it.
    352351        try:
    353             input_format = get_format('DATETIME_INPUT_FORMATS')[0]
     352            input_format = formats.get_format('DATETIME_INPUT_FORMATS')[0]
    354353            initial = datetime.datetime(*time.strptime(initial, input_format)[:6])
    355354        except (TypeError, ValueError):
    356355            pass
    class TimeInput(Input): 
    381380        # formatted by HiddenInput using formats.localize_input, which is not
    382381        # necessarily the format used for this  widget. Attempt to convert it.
    383382        try:
    384             input_format = get_format('TIME_INPUT_FORMATS')[0]
     383            input_format = formats.get_format('TIME_INPUT_FORMATS')[0]
    385384            initial = datetime.time(*time.strptime(initial, input_format)[3:6])
    386385        except (TypeError, ValueError):
    387386            pass
    class SplitHiddenDateTimeWidget(SplitDateTimeWidget): 
    771770    """
    772771    is_hidden = True
    773772
    774     def __init__(self, attrs=None):
    775         widgets = (HiddenInput(attrs=attrs), HiddenInput(attrs=attrs))
    776         super(SplitDateTimeWidget, self).__init__(widgets, attrs)
     773    def __init__(self, attrs=None, date_format=None, time_format=None):
     774        super(SplitHiddenDateTimeWidget, self).__init__(attrs, date_format, time_format)
     775        for widget in self.widgets:
     776            widget.input_type = 'hidden'
     777            widget.is_hidden = True
  • docs/ref/forms/fields.txt

    diff --git a/docs/ref/forms/fields.txt b/docs/ref/forms/fields.txt
    index 22fabb3..396e510 100644
    a b error message keys it uses. 
    259259
    260260``validators``
    261261~~~~~~~~~~~~~~
     262
    262263.. versionadded:: 1.2
    263264
    264265.. attribute:: Field.validators
    for this field. 
    268269
    269270See the :ref:`validators documentation <ref-validators>` for more information.
    270271
     272``localize``
     273~~~~~~~~~~~~
     274
     275.. versionadded:: 1.2
     276
     277.. attribute:: Field.localize
     278
     279The ``localize`` argument enables the localization of form data, input as well
     280as the rendered output.
     281
     282See the :ref:`format localization <format-localization>` documentation for
     283more information.
     284
     285
    271286Built-in ``Field`` classes
    272287--------------------------
    273288
  • docs/topics/i18n/localization.txt

    diff --git a/docs/topics/i18n/localization.txt b/docs/topics/i18n/localization.txt
    index 10e5923..8e1beae 100644
    a b Django uses different formats for different locales when guessing the format 
    268268used by the user when inputting data on forms. Note that Django uses different
    269269formats for displaying data, and for parsing it.
    270270
     271To enable a form field to localize input and output data simply use its
     272``localize`` argument::
     273
     274    class CashRegisterForm(forms.Form):
     275       product = forms.CharField()
     276       revenue = forms.DecimalField(max_digits=4, decimal_places=2, localize=True)
     277
    271278Creating custom format files
    272279----------------------------
    273280
  • tests/regressiontests/i18n/forms.py

    diff --git a/tests/regressiontests/i18n/forms.py b/tests/regressiontests/i18n/forms.py
    index 8ed834c..216d1fe 100644
    a b from django.forms.extras import SelectDateWidget 
    33from models import Company
    44
    55class I18nForm(forms.Form):
    6     decimal_field = forms.DecimalField()
    7     float_field = forms.FloatField()
    8     date_field = forms.DateField()
    9     datetime_field = forms.DateTimeField()
    10     time_field = forms.TimeField()
    11     integer_field = forms.IntegerField()
     6    decimal_field = forms.DecimalField(localize=True)
     7    float_field = forms.FloatField(localize=True)
     8    date_field = forms.DateField(localize=True)
     9    datetime_field = forms.DateTimeField(localize=True)
     10    time_field = forms.TimeField(localize=True)
     11    integer_field = forms.IntegerField(localize=True)
    1212
    1313class SelectDateForm(forms.Form):
    1414    date_field = forms.DateField(widget=SelectDateWidget)
    1515
    1616class CompanyForm(forms.ModelForm):
     17    cents_payed = forms.DecimalField(max_digits=4, decimal_places=2, localize=True)
     18    products_delivered = forms.IntegerField(localize=True)
     19
    1720    class Meta:
    1821        model = Company
  • tests/regressiontests/i18n/tests.py

    diff --git a/tests/regressiontests/i18n/tests.py b/tests/regressiontests/i18n/tests.py
    index 31150a6..9cc1089 100644
    a b class FormattingTests(TestCase): 
    410410            self.assertEqual(localize_input(datetime.datetime(2009, 12, 31, 6, 0, 0)), '31.12.2009 06:00:00')
    411411            self.assertEqual(datetime.datetime(2009, 12, 31, 6, 0, 0), form6.cleaned_data['date_added'])
    412412            settings.USE_THOUSAND_SEPARATOR = True
    413             self.assert_(u'12.000' in form6.as_ul())
     413            # Checking for the localized "products_delivered" field
     414            self.assert_(u'<input type="text" name="products_delivered" value="12.000" id="id_products_delivered" />' in form6.as_ul())
    414415        finally:
    415416            deactivate()
    416417
Back to Top