Skip to content

Commit b19d83f

Browse files
committed
Improved input sanitizing with thousand separators
For languages with non-breaking space as thousand separator, standard space input should also be allowed, as few people know how to enter non-breaking space on keyboards. Refs django#17217. Thanks Alexey Boriskin for the report and initial patch.
1 parent a8d1421 commit b19d83f

File tree

2 files changed

+32
-12
lines changed

2 files changed

+32
-12
lines changed

django/utils/formats.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import decimal
22
import datetime
3+
import unicodedata
34

45
from django.conf import settings
56
from django.utils import dateformat, numberformat, datetime_safe
@@ -192,16 +193,17 @@ def sanitize_separators(value):
192193
Sanitizes a value according to the current decimal and
193194
thousand separator setting. Used with form field input.
194195
"""
195-
if settings.USE_L10N:
196+
if settings.USE_L10N and isinstance(value, six.string_types):
197+
parts = []
196198
decimal_separator = get_format('DECIMAL_SEPARATOR')
197-
if isinstance(value, six.string_types):
198-
parts = []
199-
if decimal_separator in value:
200-
value, decimals = value.split(decimal_separator, 1)
201-
parts.append(decimals)
202-
if settings.USE_THOUSAND_SEPARATOR:
203-
parts.append(value.replace(get_format('THOUSAND_SEPARATOR'), ''))
204-
else:
205-
parts.append(value)
206-
value = '.'.join(reversed(parts))
199+
if decimal_separator in value:
200+
value, decimals = value.split(decimal_separator, 1)
201+
parts.append(decimals)
202+
if settings.USE_THOUSAND_SEPARATOR:
203+
thousand_sep = get_format('THOUSAND_SEPARATOR')
204+
for replacement in set([
205+
thousand_sep, unicodedata.normalize('NFKD', thousand_sep)]):
206+
value = value.replace(replacement, '')
207+
parts.append(value)
208+
value = '.'.join(reversed(parts))
207209
return value

tests/regressiontests/i18n/tests.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from django.utils import translation
1616
from django.utils.formats import (get_format, date_format, time_format,
1717
localize, localize_input, iter_format_modules, get_format_modules,
18-
number_format)
18+
number_format, sanitize_separators)
1919
from django.utils.importlib import import_module
2020
from django.utils.numberformat import format as nformat
2121
from django.utils._os import upath
@@ -669,6 +669,24 @@ def test_localized_input(self):
669669
# Checking for the localized "products_delivered" field
670670
self.assertInHTML('<input type="text" name="products_delivered" value="12.000" id="id_products_delivered" />', form6.as_ul())
671671

672+
def test_sanitize_separators(self):
673+
"""
674+
Tests django.utils.formats.sanitize_separators.
675+
"""
676+
# Non-strings are untouched
677+
self.assertEqual(sanitize_separators(123), 123)
678+
679+
with translation.override('ru', deactivate=True):
680+
# Russian locale has non-breaking space (\xa0) as thousand separator
681+
# Check that usual space is accepted too when sanitizing inputs
682+
with self.settings(USE_THOUSAND_SEPARATOR=True):
683+
self.assertEqual(sanitize_separators('1\xa0234\xa0567'), '1234567')
684+
self.assertEqual(sanitize_separators('77\xa0777,777'), '77777.777')
685+
self.assertEqual(sanitize_separators('12 345'), '12345')
686+
self.assertEqual(sanitize_separators('77 777,777'), '77777.777')
687+
with self.settings(USE_THOUSAND_SEPARATOR=True, USE_L10N=False):
688+
self.assertEqual(sanitize_separators('12\xa0345'), '12\xa0345')
689+
672690
def test_iter_format_modules(self):
673691
"""
674692
Tests the iter_format_modules function.

0 commit comments

Comments
 (0)