Skip to content

Add localization support to the FloatField #4925

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 25 commits into from
Oct 4, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
0316360
Merge pull request #1 from tomchristie/master
kgeorgy Feb 21, 2017
ddfce42
Merge commit 'b936d829a6b77fe344d2021ae41e89dd66eba4d4'
Feb 27, 2017
38b3064
Add the "localize" and "coerce_to_string" constructor options to the …
Feb 27, 2017
878a0a5
Merge branch 'master' into localizedfloatfield
kgeorgy Mar 3, 2017
279ffc9
Merge branch 'master' into localizedfloatfield
kgeorgy Mar 10, 2017
7daa688
Merge branch 'master' into localizedfloatfield
kgeorgy Mar 14, 2017
095cd3a
Merge branch 'master' into localizedfloatfield
kgeorgy Mar 17, 2017
26c44b0
Merge branch 'master' into localizedfloatfield
kgeorgy Mar 27, 2017
479f323
Merge branch 'master' into localizedfloatfield
kgeorgy Mar 31, 2017
5fa2b4e
Merge branch 'master' into localizedfloatfield
kgeorgy Apr 10, 2017
8b5e479
Merge branch 'master' into localizedfloatfield
kgeorgy Apr 11, 2017
3772798
Merge branch 'master' into localizedfloatfield
kgeorgy Apr 24, 2017
9705179
Merge branch 'master' into localizedfloatfield
kgeorgy May 2, 2017
855dfcd
Merge branch 'master' into localizedfloatfield
kgeorgy May 5, 2017
7f543c8
Merge branch 'master' into localizedfloatfield
kgeorgy May 12, 2017
d94b00c
Merge branch 'master' into localizedfloatfield
kgeorgy May 23, 2017
c737fa0
Merge branch 'master' into localizedfloatfield
kgeorgy Jun 26, 2017
5094299
Merge branch 'master' into localizedfloatfield
kgeorgy Jul 11, 2017
f389833
Merge branch 'master' into localizedfloatfield
kgeorgy Aug 16, 2017
bf53f74
* Restore imports in order to make isort test pass
Aug 16, 2017
fe0c4f9
Fix string identification in python2.7
Aug 16, 2017
a0c8d2f
Add documentation for the coerce_to_string and localize FloatField pa…
Aug 16, 2017
9bd6229
Merge branch 'version-3.7' into localizedfloatfield
kgeorgy Sep 28, 2017
8890539
Removes unneeded lines, and set default value for coerce_to_string to…
Oct 4, 2017
5dd01c6
Update FloatField signature docs
Oct 4, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion docs/api-guide/fields.md
Original file line number Diff line number Diff line change
Expand Up @@ -250,10 +250,12 @@ A floating point representation.

Corresponds to `django.db.models.fields.FloatField`.

**Signature**: `FloatField(max_value=None, min_value=None)`
**Signature**: `FloatField(coerce_to_string=False, max_value=None, min_value=None, localize=False)`

- `coerce_to_string` Set to `True` if string values should be returned for the representation, or `False` if `float` objects should be returned. Defaults to `False`.
- `max_value` Validate that the number provided is no greater than this value.
- `min_value` Validate that the number provided is no less than this value.
- `localize` Set to `True` to enable localization of input and output based on the current locale. This will also force `coerce_to_string` to `True`. Defaults to `False`. Note that data formatting is enabled if you have set `USE_L10N=True` in your settings file.

## DecimalField

Expand Down
21 changes: 18 additions & 3 deletions rest_framework/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@
)
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 lazy
from django.utils.ipv6 import clean_ipv6_address
from django.utils.timezone import utc
Expand Down Expand Up @@ -954,6 +956,8 @@ 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', False)
super(FloatField, self).__init__(**kwargs)
if self.max_value is not None:
message = lazy(
Expand All @@ -970,15 +974,26 @@ def __init__(self, **kwargs):

def to_internal_value(self, data):

if isinstance(data, six.text_type) and len(data) > self.MAX_STRING_LENGTH:
self.fail('max_string_length')
if isinstance(data, six.string_types):

data = smart_text(data).strip()

if len(data) > self.MAX_STRING_LENGTH:
self.fail('max_string_length')

if self.localize:
data = sanitize_separators(data)

try:
return float(data)
except (TypeError, ValueError):
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)


Expand Down
30 changes: 30 additions & 0 deletions tests/test_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -952,6 +952,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`.
Expand Down