Add the "localize" and "coerce_to_string" constructor options to the FloatField like it is done for the DecimalField, in order to use the user current local to serialise and deserialise the float value if required.

This commit is contained in:
Kevin Georgy 2017-02-27 13:04:43 +01:00
parent ddfce425fa
commit 38b306426c
2 changed files with 47 additions and 2 deletions

View File

@ -25,7 +25,9 @@ from django.utils.dateparse import (
)
from django.utils.duration import duration_string
from django.utils.encoding import is_protected_type, smart_text
from django.utils.formats import localize_input, sanitize_separators
from django.utils.formats import (
localize_input, number_format, sanitize_separators
)
from django.utils.functional import cached_property
from django.utils.ipv6 import clean_ipv6_address
from django.utils.timezone import utc
@ -920,6 +922,10 @@ class FloatField(Field):
def __init__(self, **kwargs):
self.max_value = kwargs.pop('max_value', None)
self.min_value = kwargs.pop('min_value', None)
self.localize = kwargs.pop('localize', False)
self.coerce_to_string = kwargs.pop('coerce_to_string', None)
if self.localize:
self.coerce_to_string = True
super(FloatField, self).__init__(**kwargs)
if self.max_value is not None:
message = self.error_messages['max_value'].format(max_value=self.max_value)
@ -930,7 +936,12 @@ class FloatField(Field):
def to_internal_value(self, data):
if isinstance(data, six.text_type) and len(data) > self.MAX_STRING_LENGTH:
data = smart_text(data).strip()
if self.localize:
data = sanitize_separators(data)
if len(data) > self.MAX_STRING_LENGTH:
self.fail('max_string_length')
try:
@ -939,6 +950,10 @@ class FloatField(Field):
self.fail('invalid')
def to_representation(self, value):
if self.localize:
return number_format(value)
if self.coerce_to_string:
return str(float(value))
return float(value)

View File

@ -922,6 +922,36 @@ class TestMinMaxFloatField(FieldValues):
field = serializers.FloatField(min_value=1, max_value=3)
class TestCoerceToStringFloatField(FieldValues):
valid_inputs = {}
invalid_inputs = {}
outputs = {
'1': str(1.0),
'0': str(0.0),
1: str(1.0),
0: str(0.0),
1.5: str(1.5),
}
field = serializers.FloatField(coerce_to_string=True)
class TestLocalizedFloatField(TestCase):
@override_settings(USE_L10N=True, LANGUAGE_CODE='it')
def test_to_internal_value(self):
field = serializers.FloatField(localize=True)
self.assertEqual(field.to_internal_value('1,5'), 1.5)
@override_settings(USE_L10N=True, LANGUAGE_CODE=None, DECIMAL_SEPARATOR=',', THOUSAND_SEPARATOR='\'',
NUMBER_GROUPING=3, USE_THOUSAND_SEPARATOR=True)
def test_to_representation(self):
field = serializers.FloatField(localize=True)
self.assertEqual(field.to_representation(1000.75), '1\'000,75')
def test_localize_forces_coerce_to_string(self):
field = serializers.FloatField(localize=True)
self.assertTrue(isinstance(field.to_representation(3), six.string_types))
class TestDecimalField(FieldValues):
"""
Valid and invalid values for `DecimalField`.