Ticket #12779: 12779.1.diff

File 12779.1.diff, 14.9 KB (added by jezdez, 5 years ago)

Adding ability to sanitize the seperators contained in form field input

  • django/forms/fields.py

    diff --git a/django/forms/fields.py b/django/forms/fields.py
    index 6d0fdea..b31fe80 100644
    a b except ImportError: 
    1717from django.core.exceptions import ValidationError
    1818from django.core import validators
    1919import django.utils.copycompat as copy
     20from django.utils import formats
    2021from django.utils.translation import ugettext_lazy as _
    2122from django.utils.encoding import smart_unicode, smart_str
    22 from django.utils.formats import get_format
    2323from django.utils.functional import lazy
    2424
    2525# Provide this import for backwards compatibility.
    class IntegerField(Field): 
    213213        value = super(IntegerField, self).to_python(value)
    214214        if value in validators.EMPTY_VALUES:
    215215            return None
    216 
     216        value = formats.sanitize_separators(value)
    217217        try:
    218218            value = int(str(value))
    219219        except (ValueError, TypeError):
    class FloatField(IntegerField): 
    233233        value = super(IntegerField, self).to_python(value)
    234234        if value in validators.EMPTY_VALUES:
    235235            return None
    236 
     236        value = formats.sanitize_separators(value)
    237237        try:
    238             # We always accept dot as decimal separator
    239             if isinstance(value, str) or isinstance(value, unicode):
    240                 value = float(value.replace(get_format('DECIMAL_SEPARATOR'), '.'))
     238            value = float(value)
    241239        except (ValueError, TypeError):
    242240            raise ValidationError(self.error_messages['invalid'])
    243241        return value
    class DecimalField(Field): 
    270268        """
    271269        if value in validators.EMPTY_VALUES:
    272270            return None
     271        value = formats.sanitize_separators(value)
    273272        value = smart_str(value).strip()
    274273        try:
    275             # We always accept dot as decimal separator
    276             if isinstance(value, str) or isinstance(value, unicode):
    277                 value = Decimal(value.replace(get_format('DECIMAL_SEPARATOR'), '.'))
     274            value = Decimal(value)
    278275        except DecimalException:
    279276            raise ValidationError(self.error_messages['invalid'])
    280277        return value
    class DateField(Field): 
    329326            return value.date()
    330327        if isinstance(value, datetime.date):
    331328            return value
    332         for format in self.input_formats or get_format('DATE_INPUT_FORMATS'):
     329        for format in self.input_formats or formats.get_format('DATE_INPUT_FORMATS'):
    333330            try:
    334331                return datetime.date(*time.strptime(value, format)[:3])
    335332            except ValueError:
    class TimeField(Field): 
    355352            return None
    356353        if isinstance(value, datetime.time):
    357354            return value
    358         for format in self.input_formats or get_format('TIME_INPUT_FORMATS'):
     355        for format in self.input_formats or formats.get_format('TIME_INPUT_FORMATS'):
    359356            try:
    360357                return datetime.time(*time.strptime(value, format)[3:6])
    361358            except ValueError:
    class DateTimeField(Field): 
    389386            if len(value) != 2:
    390387                raise ValidationError(self.error_messages['invalid'])
    391388            value = '%s %s' % tuple(value)
    392         for format in self.input_formats or get_format('DATETIME_INPUT_FORMATS'):
     389        for format in self.input_formats or formats.get_format('DATETIME_INPUT_FORMATS'):
    393390            try:
    394391                return datetime.datetime(*time.strptime(value, format)[:6])
    395392            except ValueError:
  • django/utils/formats.py

    diff --git a/django/utils/formats.py b/django/utils/formats.py
    index 88f744b..31027ab 100644
    a b def localize_input(value, default=None): 
    109109        format = smart_str(default or get_format('TIME_INPUT_FORMATS')[0])
    110110        return value.strftime(format)
    111111    return value
     112
     113def sanitize_separators(value):
     114    """
     115    Sanitizes a value according to the current decimal and
     116    thousand separator setting. Used with form field input.
     117    """
     118    if settings.USE_L10N:
     119        decimal_separator = get_format('DECIMAL_SEPARATOR')
     120        if isinstance(value, basestring):
     121            parts = []
     122            if decimal_separator in value:
     123                value, decimals = value.split(decimal_separator, 1)
     124                parts.append(decimals)
     125            if settings.USE_THOUSAND_SEPARATOR:
     126                parts.append(value.replace(get_format('THOUSAND_SEPARATOR'), ''))
     127            else:
     128                parts.append(value)
     129            value = '.'.join(reversed(parts))
     130    return value
  • tests/regressiontests/i18n/forms.py

    diff --git a/tests/regressiontests/i18n/forms.py b/tests/regressiontests/i18n/forms.py
    index 8df066c..8ed834c 100644
    a b class I18nForm(forms.Form): 
    88    date_field = forms.DateField()
    99    datetime_field = forms.DateTimeField()
    1010    time_field = forms.TimeField()
     11    integer_field = forms.IntegerField()
    1112
    1213class SelectDateForm(forms.Form):
    1314    date_field = forms.DateField(widget=SelectDateWidget)
  • tests/regressiontests/i18n/models.py

    diff --git a/tests/regressiontests/i18n/models.py b/tests/regressiontests/i18n/models.py
    index 2ff5fc4..8b142b3 100644
    a b class Company(models.Model): 
    99    name = models.CharField(max_length=50)
    1010    date_added = models.DateTimeField(default=datetime(1799,1,31,23,59,59,0))
    1111    cents_payed = models.DecimalField(max_digits=4, decimal_places=2)
     12    products_delivered = models.IntegerField()
    1213
    1314__test__ = {'API_TESTS': '''
    1415>>> tm = TestModel()
  • tests/regressiontests/i18n/tests.py

    diff --git a/tests/regressiontests/i18n/tests.py b/tests/regressiontests/i18n/tests.py
    index a4d0d90..6b53fe5 100644
    a b class FormattingTests(TestCase): 
    179179                'float_field': u'99999,999',
    180180                'date_field': u'31/12/2009',
    181181                'datetime_field': u'31/12/2009 20:50',
    182                 'time_field': u'20:50'
     182                'time_field': u'20:50',
     183                'integer_field': u'1.234',
    183184            })
    184185            self.assertEqual(False, form.is_valid())
    185186            self.assertEqual([u'Introdu\xefu un n\xfamero.'], form.errors['float_field'])
    186187            self.assertEqual([u'Introdu\xefu un n\xfamero.'], form.errors['decimal_field'])
    187188            self.assertEqual([u'Introdu\xefu una data v\xe0lida.'], form.errors['date_field'])
    188189            self.assertEqual([u'Introdu\xefu una data/hora v\xe0lides.'], form.errors['datetime_field'])
     190            self.assertEqual([u'Introdu\xefu un n\xfamero sencer.'], form.errors['integer_field'])
    189191
    190192            form2 = SelectDateForm({
    191193                'date_field_month': u'12',
    class FormattingTests(TestCase): 
    231233            self.assertEqual(u'66.666,666', Template('{{ n }}').render(self.ctxt))
    232234            self.assertEqual(u'99.999,999', Template('{{ f }}').render(self.ctxt))
    233235
     236            form3 = I18nForm({
     237                'decimal_field': u'66.666,666',
     238                'float_field': u'99.999,999',
     239                'date_field': u'31/12/2009',
     240                'datetime_field': u'31/12/2009 20:50',
     241                'time_field': u'20:50',
     242                'integer_field': u'1.234',
     243            })
     244            self.assertEqual(True, form3.is_valid())
     245            self.assertEqual(decimal.Decimal('66666.666'), form3.cleaned_data['decimal_field'])
     246            self.assertEqual(99999.999, form3.cleaned_data['float_field'])
     247            self.assertEqual(datetime.date(2009, 12, 31), form3.cleaned_data['date_field'])
     248            self.assertEqual(datetime.datetime(2009, 12, 31, 20, 50), form3.cleaned_data['datetime_field'])
     249            self.assertEqual(datetime.time(20, 50), form3.cleaned_data['time_field'])
     250            self.assertEqual(1234, form3.cleaned_data['integer_field'])
     251
    234252            settings.USE_THOUSAND_SEPARATOR = False
    235253            self.assertEqual(u'66666,666', Template('{{ n }}').render(self.ctxt))
    236254            self.assertEqual(u'99999,999', Template('{{ f }}').render(self.ctxt))
    class FormattingTests(TestCase): 
    242260            self.assertEqual(u'31/12/2009', Template('{{ d|date:"SHORT_DATE_FORMAT" }}').render(self.ctxt))
    243261            self.assertEqual(u'31/12/2009 20:50', Template('{{ dt|date:"SHORT_DATETIME_FORMAT" }}').render(self.ctxt))
    244262
    245             form3 = I18nForm({
     263            form4 = I18nForm({
    246264                'decimal_field': u'66666,666',
    247265                'float_field': u'99999,999',
    248266                'date_field': u'31/12/2009',
    249267                'datetime_field': u'31/12/2009 20:50',
    250                 'time_field': u'20:50'
     268                'time_field': u'20:50',
     269                'integer_field': u'1234',
    251270            })
    252             self.assertEqual(True, form3.is_valid())
    253             self.assertEqual(decimal.Decimal('66666.666'), form3.cleaned_data['decimal_field'])
    254             self.assertEqual(99999.999, form3.cleaned_data['float_field'])
    255             self.assertEqual(datetime.date(2009, 12, 31), form3.cleaned_data['date_field'])
    256             self.assertEqual(datetime.datetime(2009, 12, 31, 20, 50), form3.cleaned_data['datetime_field'])
    257             self.assertEqual(datetime.time(20, 50), form3.cleaned_data['time_field'])
     271            self.assertEqual(True, form4.is_valid())
     272            self.assertEqual(decimal.Decimal('66666.666'), form4.cleaned_data['decimal_field'])
     273            self.assertEqual(99999.999, form4.cleaned_data['float_field'])
     274            self.assertEqual(datetime.date(2009, 12, 31), form4.cleaned_data['date_field'])
     275            self.assertEqual(datetime.datetime(2009, 12, 31, 20, 50), form4.cleaned_data['datetime_field'])
     276            self.assertEqual(datetime.time(20, 50), form4.cleaned_data['time_field'])
     277            self.assertEqual(1234, form4.cleaned_data['integer_field'])
    258278
    259             form4 = SelectDateForm({
     279            form5 = SelectDateForm({
    260280                'date_field_month': u'12',
    261281                'date_field_day': u'31',
    262282                'date_field_year': u'2009'
    263283            })
    264             self.assertEqual(True, form4.is_valid())
    265             self.assertEqual(datetime.date(2009, 12, 31), form4.cleaned_data['date_field'])
     284            self.assertEqual(True, form5.is_valid())
     285            self.assertEqual(datetime.date(2009, 12, 31), form5.cleaned_data['date_field'])
    266286            self.assertEqual(
    267287                u'<select name="mydate_day" id="id_mydate_day">\n<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="4">4</option>\n<option value="5">5</option>\n<option value="6">6</option>\n<option value="7">7</option>\n<option value="8">8</option>\n<option value="9">9</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31" selected="selected">31</option>\n</select>\n<select name="mydate_month" id="id_mydate_month">\n<option value="1">gener</option>\n<option value="2">febrer</option>\n<option value="3">mar\xe7</option>\n<option value="4">abril</option>\n<option value="5">maig</option>\n<option value="6">juny</option>\n<option value="7">juliol</option>\n<option value="8">agost</option>\n<option value="9">setembre</option>\n<option value="10">octubre</option>\n<option value="11">novembre</option>\n<option value="12" selected="selected">desembre</option>\n</select>\n<select name="mydate_year" id="id_mydate_year">\n<option value="2009" selected="selected">2009</option>\n<option value="2010">2010</option>\n<option value="2011">2011</option>\n<option value="2012">2012</option>\n<option value="2013">2013</option>\n<option value="2014">2014</option>\n<option value="2015">2015</option>\n<option value="2016">2016</option>\n<option value="2017">2017</option>\n<option value="2018">2018</option>\n</select>',
    268288                SelectDateWidget(years=range(2009, 2019)).render('mydate', datetime.date(2009, 12, 31))
    class FormattingTests(TestCase): 
    312332                'float_field': u'99999.999',
    313333                'date_field': u'12/31/2009',
    314334                'datetime_field': u'12/31/2009 20:50',
    315                 'time_field': u'20:50'
     335                'time_field': u'20:50',
     336                'integer_field': u'1234',
    316337            })
    317338            self.assertEqual(True, form5.is_valid())
    318339            self.assertEqual(decimal.Decimal('66666.666'), form5.cleaned_data['decimal_field'])
    class FormattingTests(TestCase): 
    320341            self.assertEqual(datetime.date(2009, 12, 31), form5.cleaned_data['date_field'])
    321342            self.assertEqual(datetime.datetime(2009, 12, 31, 20, 50), form5.cleaned_data['datetime_field'])
    322343            self.assertEqual(datetime.time(20, 50), form5.cleaned_data['time_field'])
     344            self.assertEqual(1234, form5.cleaned_data['integer_field'])
    323345
    324346            form6 = SelectDateForm({
    325347                'date_field_month': u'12',
    class FormattingTests(TestCase): 
    364386                'name': u'acme',
    365387                'date_added': datetime.datetime(2009, 12, 31, 6, 0, 0),
    366388                'cents_payed': decimal.Decimal('59.47'),
     389                'products_delivered': 12,
    367390            })
    368391            form6.save()
    369392            self.assertEqual(True, form6.is_valid())
    370393            self.assertEqual(
    371394                form6.as_ul(),
    372                 u'<li><label for="id_name">Name:</label> <input id="id_name" type="text" name="name" value="acme" maxlength="50" /></li>\n<li><label for="id_date_added">Date added:</label> <input type="text" name="date_added" value="31.12.2009 06:00:00" id="id_date_added" /></li>\n<li><label for="id_cents_payed">Cents payed:</label> <input type="text" name="cents_payed" value="59,47" id="id_cents_payed" /></li>'
     395                u'<li><label for="id_name">Name:</label> <input id="id_name" type="text" name="name" value="acme" maxlength="50" /></li>\n<li><label for="id_date_added">Date added:</label> <input type="text" name="date_added" value="31.12.2009 06:00:00" id="id_date_added" /></li>\n<li><label for="id_cents_payed">Cents payed:</label> <input type="text" name="cents_payed" value="59,47" id="id_cents_payed" /></li>\n<li><label for="id_products_delivered">Products delivered:</label> <input type="text" name="products_delivered" value="12" id="id_products_delivered" /></li>'
    373396            )
    374397            self.assertEqual(localize_input(datetime.datetime(2009, 12, 31, 6, 0, 0)), '31.12.2009 06:00:00')
    375398            self.assertEqual(datetime.datetime(2009, 12, 31, 6, 0, 0), form6.cleaned_data['date_added'])
Back to Top