localize for DecimalField and FloatField

This commit is contained in:
kiyoqoko 2016-06-30 13:26:03 +02:00 committed by bryst
parent 1d2fba906e
commit dcf7f16abd
2 changed files with 43 additions and 2 deletions

View File

@ -25,6 +25,7 @@ from django.utils.dateparse import (
) )
from django.utils.duration import duration_string from django.utils.duration import duration_string
from django.utils.encoding import is_protected_type, smart_text from django.utils.encoding import is_protected_type, smart_text
from django.utils.formats import localize_input, sanitize_separators
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.utils.ipv6 import clean_ipv6_address from django.utils.ipv6 import clean_ipv6_address
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
@ -275,7 +276,7 @@ class Field(object):
def __init__(self, read_only=False, write_only=False, def __init__(self, read_only=False, write_only=False,
required=None, default=empty, initial=empty, source=None, required=None, default=empty, initial=empty, source=None,
label=None, help_text=None, style=None, label=None, help_text=None, style=None,
error_messages=None, validators=None, allow_null=False): error_messages=None, validators=None, allow_null=False, localize=False):
self._creation_counter = Field._creation_counter self._creation_counter = Field._creation_counter
Field._creation_counter += 1 Field._creation_counter += 1
@ -299,6 +300,7 @@ class Field(object):
self.help_text = help_text self.help_text = help_text
self.style = {} if style is None else style self.style = {} if style is None else style
self.allow_null = allow_null self.allow_null = allow_null
self.localize = localize
if self.default_empty_html is not empty: if self.default_empty_html is not empty:
if default is not empty: if default is not empty:
@ -871,6 +873,9 @@ class FloatField(Field):
self.validators.append(MinValueValidator(self.min_value, message=message)) self.validators.append(MinValueValidator(self.min_value, message=message))
def to_internal_value(self, data): def to_internal_value(self, data):
if self.localize:
data = sanitize_separators(data)
if isinstance(data, six.text_type) and len(data) > self.MAX_STRING_LENGTH: if isinstance(data, six.text_type) and len(data) > self.MAX_STRING_LENGTH:
self.fail('max_string_length') self.fail('max_string_length')
@ -880,7 +885,10 @@ class FloatField(Field):
self.fail('invalid') self.fail('invalid')
def to_representation(self, value): def to_representation(self, value):
return float(value) value = float(value)
if self.localize:
value = localize_input(value)
return value
class DecimalField(Field): class DecimalField(Field):
@ -923,7 +931,12 @@ class DecimalField(Field):
Validate that the input is a decimal number and return a Decimal Validate that the input is a decimal number and return a Decimal
instance. instance.
""" """
if self.localize:
data = sanitize_separators(data)
data = smart_text(data).strip() data = smart_text(data).strip()
if len(data) > self.MAX_STRING_LENGTH: if len(data) > self.MAX_STRING_LENGTH:
self.fail('max_string_length') self.fail('max_string_length')
@ -988,6 +1001,9 @@ class DecimalField(Field):
if not coerce_to_string: if not coerce_to_string:
return quantized return quantized
if self.localize:
return localize_input(quantized)
return '{0:f}'.format(quantized) return '{0:f}'.format(quantized)
def quantize(self, value): def quantize(self, value):

View File

@ -5,6 +5,7 @@ from decimal import Decimal
import pytest import pytest
from django.http import QueryDict from django.http import QueryDict
from django.test import TestCase, override_settings
from django.utils import six, timezone from django.utils import six, timezone
import rest_framework import rest_framework
@ -894,6 +895,30 @@ class TestNoStringCoercionDecimalField(FieldValues):
) )
class TestLocalizedDecimalField(TestCase):
@override_settings(USE_L10N=True, LANGUAGE_CODE='pl', LANGUAGES=(('pl', 'Polish'),))
def test_to_internal_value(self):
field = serializers.DecimalField(max_digits=2, decimal_places=1, localize=True)
self.assertEqual(field.to_internal_value('1,1'), Decimal('1.1'))
@override_settings(USE_L10N=True, LANGUAGE_CODE='pl', LANGUAGES=(('pl', 'Polish'),))
def test_to_representation(self):
field = serializers.DecimalField(max_digits=2, decimal_places=1, localize=True)
self.assertEqual(field.to_representation(Decimal('1.1')), '1,1')
class TestLocalizedFloatField(TestCase):
@override_settings(USE_L10N=True, LANGUAGE_CODE='pl', LANGUAGES=(('pl', 'Polish'),))
def test_to_internal_value(self):
field = serializers.FloatField(localize=True)
self.assertEqual(field.to_internal_value('1,1'), 1.1)
@override_settings(USE_L10N=True, LANGUAGE_CODE='pl', LANGUAGES=(('pl', 'Polish'),))
def test_to_representation(self):
field = serializers.FloatField(localize=True)
self.assertEqual(field.to_representation(1.1), '1,1')
class TestNoDecimalPlaces(FieldValues): class TestNoDecimalPlaces(FieldValues):
valid_inputs = { valid_inputs = {
'0.12345': Decimal('0.12345'), '0.12345': Decimal('0.12345'),