From 3038e2b07fd1b01c7cc5e120c69891c7477a04a6 Mon Sep 17 00:00:00 2001 From: Omer Katz Date: Wed, 12 Feb 2014 21:10:46 +0200 Subject: [PATCH 01/10] The default empty value is now quantized according to the specified decimal_places argument. --- rest_framework/fields.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_framework/fields.py b/rest_framework/fields.py index 05daaab76..46ca2346d 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -849,7 +849,6 @@ class DecimalField(WritableField): type_name = 'DecimalField' type_label = 'decimal' form_field_class = forms.DecimalField - empty = Decimal('0') default_error_messages = { 'invalid': _('Enter a number.'), @@ -863,6 +862,7 @@ class DecimalField(WritableField): def __init__(self, max_value=None, min_value=None, max_digits=None, decimal_places=None, *args, **kwargs): self.max_value, self.min_value = max_value, min_value self.max_digits, self.decimal_places = max_digits, decimal_places + self.empty = Decimal('0').qauntize(Decimal('.%s1' % ('0' * self.decimal_places))) super(DecimalField, self).__init__(*args, **kwargs) if max_value is not None: From bd3d0370a5445e413b95f955d217e4f472cad3f9 Mon Sep 17 00:00:00 2001 From: Omer Katz Date: Wed, 12 Feb 2014 21:18:54 +0200 Subject: [PATCH 02/10] Fixed typo. --- rest_framework/fields.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_framework/fields.py b/rest_framework/fields.py index 46ca2346d..fd1259052 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -862,7 +862,7 @@ class DecimalField(WritableField): def __init__(self, max_value=None, min_value=None, max_digits=None, decimal_places=None, *args, **kwargs): self.max_value, self.min_value = max_value, min_value self.max_digits, self.decimal_places = max_digits, decimal_places - self.empty = Decimal('0').qauntize(Decimal('.%s1' % ('0' * self.decimal_places))) + self.empty = Decimal('0').quantize(Decimal('.%s1' % ('0' * self.decimal_places))) super(DecimalField, self).__init__(*args, **kwargs) if max_value is not None: From b4d8976b923b9835cae65a184919a154838784bc Mon Sep 17 00:00:00 2001 From: Omer Katz Date: Wed, 12 Feb 2014 21:48:58 +0200 Subject: [PATCH 03/10] When decimal places is none, don't quantize. --- rest_framework/fields.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/rest_framework/fields.py b/rest_framework/fields.py index fd1259052..9c604edd1 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -849,6 +849,7 @@ class DecimalField(WritableField): type_name = 'DecimalField' type_label = 'decimal' form_field_class = forms.DecimalField + empty = Decimal('0') default_error_messages = { 'invalid': _('Enter a number.'), @@ -862,7 +863,10 @@ class DecimalField(WritableField): def __init__(self, max_value=None, min_value=None, max_digits=None, decimal_places=None, *args, **kwargs): self.max_value, self.min_value = max_value, min_value self.max_digits, self.decimal_places = max_digits, decimal_places - self.empty = Decimal('0').quantize(Decimal('.%s1' % ('0' * self.decimal_places))) + + if self.decimal_places: + self.empty = Decimal('0').quantize(Decimal('.%s1' % ('0' * self.decimal_places or 0))) + super(DecimalField, self).__init__(*args, **kwargs) if max_value is not None: From 24572a17be95a655ef56cabea06539aab8259258 Mon Sep 17 00:00:00 2001 From: Omer Katz Date: Wed, 12 Feb 2014 22:05:57 +0200 Subject: [PATCH 04/10] Added tests for default decimal value quantization. --- rest_framework/tests/test_fields.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/rest_framework/tests/test_fields.py b/rest_framework/tests/test_fields.py index e127feef9..1b5345ee1 100644 --- a/rest_framework/tests/test_fields.py +++ b/rest_framework/tests/test_fields.py @@ -626,7 +626,23 @@ class DecimalFieldTest(TestCase): self.assertFalse(DecimalSerializer(data={'decimal_field': '8000'}).is_valid()) self.assertFalse(DecimalSerializer(data={'decimal_field': '9900'}).is_valid()) self.assertFalse(DecimalSerializer(data={'decimal_field': '9001.234'}).is_valid()) - + + def test_decimal_is_not_quantized_when_decimal_places_is_none(self): + class DecimalSerializer(serializers.Serializer): + decimal_field = serializers.DecimalField(required=False) + serializer = DecimalSerializer(data={}) + + self.assertTrue(serializer.is_valid()) + self.assertTrue(serializer.data['decimal_field'].as_tuple().exponent, 0) + + def test_decimal_is_quantized_when_decimal_places_is_provided(self): + class DecimalSerializer(serializers.Serializer): + decimal_field = serializers.DecimalField(required=False, decimal_places=2) + serializer = DecimalSerializer(data={}) + + self.assertTrue(serializer.is_valid()) + self.assertTrue(serializer.data['decimal_field'].as_tuple().exponent, -2) + def test_raise_max_value(self): """ Make sure max_value violations raises ValidationError From 8acb06b636b9946988ac3319586dc0c8712fbf76 Mon Sep 17 00:00:00 2001 From: Omer Katz Date: Wed, 12 Feb 2014 22:07:50 +0200 Subject: [PATCH 05/10] One decimal place is always present when decimal places is specified. --- rest_framework/fields.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_framework/fields.py b/rest_framework/fields.py index 9c604edd1..3c7fcf172 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -865,7 +865,7 @@ class DecimalField(WritableField): self.max_digits, self.decimal_places = max_digits, decimal_places if self.decimal_places: - self.empty = Decimal('0').quantize(Decimal('.%s1' % ('0' * self.decimal_places or 0))) + self.empty = Decimal('0').quantize(Decimal('.%s1' % ('0' * self.decimal_places - 1))) super(DecimalField, self).__init__(*args, **kwargs) From 56716f490b0978a7ae17ec4f184998950575b0c0 Mon Sep 17 00:00:00 2001 From: Omer Katz Date: Wed, 12 Feb 2014 22:12:03 +0200 Subject: [PATCH 06/10] Substracted the decimal_places argument and not the string. --- rest_framework/fields.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_framework/fields.py b/rest_framework/fields.py index 3c7fcf172..424286015 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -865,7 +865,7 @@ class DecimalField(WritableField): self.max_digits, self.decimal_places = max_digits, decimal_places if self.decimal_places: - self.empty = Decimal('0').quantize(Decimal('.%s1' % ('0' * self.decimal_places - 1))) + self.empty = Decimal('0').quantize(Decimal('.%s1' % ('0' * (self.decimal_places - 1)))) super(DecimalField, self).__init__(*args, **kwargs) From bedc0f7e508b8a92389eeabe38ea9ffbcc9a4a90 Mon Sep 17 00:00:00 2001 From: Omer Katz Date: Thu, 13 Feb 2014 09:38:36 +0200 Subject: [PATCH 07/10] Using a model serializer in order to try and reproduce the problem. --- rest_framework/tests/test_fields.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/rest_framework/tests/test_fields.py b/rest_framework/tests/test_fields.py index 1b5345ee1..a4d164712 100644 --- a/rest_framework/tests/test_fields.py +++ b/rest_framework/tests/test_fields.py @@ -628,16 +628,26 @@ class DecimalFieldTest(TestCase): self.assertFalse(DecimalSerializer(data={'decimal_field': '9001.234'}).is_valid()) def test_decimal_is_not_quantized_when_decimal_places_is_none(self): - class DecimalSerializer(serializers.Serializer): - decimal_field = serializers.DecimalField(required=False) - serializer = DecimalSerializer(data={}) + class LongDecimalFieldModel(models.Model): + decimal_field = models.DecimalField(max_digits=20, decimal_places=10, default=0) + + class DecimalSerializer((serializers.ModelSerializer): + class Meta: + model = LongDecimalFieldMode + decimal_field = serializers.DecimalField(required=False, decimal_places=2) self.assertTrue(serializer.is_valid()) self.assertTrue(serializer.data['decimal_field'].as_tuple().exponent, 0) def test_decimal_is_quantized_when_decimal_places_is_provided(self): - class DecimalSerializer(serializers.Serializer): + class LongDecimalFieldModel(models.Model): + decimal_field = models.DecimalField(max_digits=20, decimal_places=10, default=0) + + class DecimalSerializer((serializers.ModelSerializer): + class Meta: + model = LongDecimalFieldMode decimal_field = serializers.DecimalField(required=False, decimal_places=2) + serializer = DecimalSerializer(data={}) self.assertTrue(serializer.is_valid()) From 9b6e0d678ae297b886680aae9debb85a957faab5 Mon Sep 17 00:00:00 2001 From: Omer Katz Date: Thu, 13 Feb 2014 09:42:39 +0200 Subject: [PATCH 08/10] Fixed syntax errors. --- rest_framework/tests/test_fields.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rest_framework/tests/test_fields.py b/rest_framework/tests/test_fields.py index a4d164712..8126af4df 100644 --- a/rest_framework/tests/test_fields.py +++ b/rest_framework/tests/test_fields.py @@ -631,9 +631,9 @@ class DecimalFieldTest(TestCase): class LongDecimalFieldModel(models.Model): decimal_field = models.DecimalField(max_digits=20, decimal_places=10, default=0) - class DecimalSerializer((serializers.ModelSerializer): + class DecimalSerializer(serializers.ModelSerializer): class Meta: - model = LongDecimalFieldMode + model = LongDecimalFieldModel decimal_field = serializers.DecimalField(required=False, decimal_places=2) self.assertTrue(serializer.is_valid()) @@ -643,9 +643,9 @@ class DecimalFieldTest(TestCase): class LongDecimalFieldModel(models.Model): decimal_field = models.DecimalField(max_digits=20, decimal_places=10, default=0) - class DecimalSerializer((serializers.ModelSerializer): + class DecimalSerializer(serializers.ModelSerializer): class Meta: - model = LongDecimalFieldMode + model = LongDecimalFieldModel decimal_field = serializers.DecimalField(required=False, decimal_places=2) serializer = DecimalSerializer(data={}) From 7842c102b4d9604d34913a93d01ce45365eb7295 Mon Sep 17 00:00:00 2001 From: Omer Katz Date: Thu, 13 Feb 2014 09:46:30 +0200 Subject: [PATCH 09/10] Added missing serializer object. --- rest_framework/tests/test_fields.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rest_framework/tests/test_fields.py b/rest_framework/tests/test_fields.py index 8126af4df..02f689a20 100644 --- a/rest_framework/tests/test_fields.py +++ b/rest_framework/tests/test_fields.py @@ -636,6 +636,8 @@ class DecimalFieldTest(TestCase): model = LongDecimalFieldModel decimal_field = serializers.DecimalField(required=False, decimal_places=2) + serializer = DecimalSerializer(data={}) + self.assertTrue(serializer.is_valid()) self.assertTrue(serializer.data['decimal_field'].as_tuple().exponent, 0) From 64a6ac68a09ba88d9b21dd293b165c8cd756f431 Mon Sep 17 00:00:00 2001 From: Omer Katz Date: Tue, 18 Mar 2014 21:29:21 +0200 Subject: [PATCH 10/10] Fixed wrong assertions. --- rest_framework/tests/test_fields.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rest_framework/tests/test_fields.py b/rest_framework/tests/test_fields.py index 02f689a20..ffb84d847 100644 --- a/rest_framework/tests/test_fields.py +++ b/rest_framework/tests/test_fields.py @@ -639,7 +639,7 @@ class DecimalFieldTest(TestCase): serializer = DecimalSerializer(data={}) self.assertTrue(serializer.is_valid()) - self.assertTrue(serializer.data['decimal_field'].as_tuple().exponent, 0) + self.assertEqual(serializer.data['decimal_field'].as_tuple().exponent, 0) def test_decimal_is_quantized_when_decimal_places_is_provided(self): class LongDecimalFieldModel(models.Model): @@ -653,7 +653,7 @@ class DecimalFieldTest(TestCase): serializer = DecimalSerializer(data={}) self.assertTrue(serializer.is_valid()) - self.assertTrue(serializer.data['decimal_field'].as_tuple().exponent, -2) + self.assertEqual(serializer.data['decimal_field'].as_tuple().exponent, -2) def test_raise_max_value(self): """