Repository: encode/django-rest-framework

Issue:
Invalid data type assigned into model while update
I'm not really sure if it's DRF of Django issue. It seems that input should (?) be modified for DecimalField before it ends up at `.validated_data`. Otherwise one can pass an `int` and retured object from `.save()` would be a incorrect.

Code:

``` python
class Product(models.Model):
    title = models.CharField(max_length=100)
    price = models.DecimalField(
        max_digits=8,
        decimal_places=2,
        default=Decimal('0.00'),
        validators=[MinValueValidator(Decimal(0))],)

class ProductSerializer(serializers.ModelSerializer):
      class Meta:
            model = Product
            fields = ('title', 'price')

# create product instance
s = ProductSerializer(data={'title': 'Test', price: 100})
s.is_valid()
obj = s.save()
```

`obj.price` would be `(Decimal) 100` and not `(Decimal) 100.00`, however `serializer.data['price']` would be correctly formatted: `(Decimal) 100.00`; It's confusing and forces users to do `obj.refresh_from_db()` if one wants to use returned object and not `serializer.data` in their code.



Discussion:
Ok, thanks for raising this

Milestoning to review further.


Resolving patch:
diff --git a/rest_framework/fields.py b/rest_framework/fields.py
--- a/rest_framework/fields.py
+++ b/rest_framework/fields.py
@@ -955,7 +955,7 @@ def to_internal_value(self, data):
         if value in (decimal.Decimal('Inf'), decimal.Decimal('-Inf')):
             self.fail('invalid')
 
-        return self.validate_precision(value)
+        return self.quantize(self.validate_precision(value))
 
     def validate_precision(self, value):
         """
@@ -1018,7 +1018,8 @@ def quantize(self, value):
         context.prec = self.max_digits
         return value.quantize(
             decimal.Decimal('.1') ** self.decimal_places,
-            context=context)
+            context=context
+        )
 
 
 # Date & time fields...


Test patch:
diff --git a/tests/test_fields.py b/tests/test_fields.py
--- a/tests/test_fields.py
+++ b/tests/test_fields.py
@@ -912,6 +912,26 @@ def test_localize_forces_coerce_to_string(self):
         self.assertTrue(isinstance(field.to_representation(Decimal('1.1')), six.string_types))
 
 
+class TestQuantizedValueForDecimal(TestCase):
+    def test_int_quantized_value_for_decimal(self):
+        field = serializers.DecimalField(max_digits=4, decimal_places=2)
+        value = field.to_internal_value(12).as_tuple()
+        expected_digit_tuple = (0, (1, 2, 0, 0), -2)
+        self.assertEqual(value, expected_digit_tuple)
+
+    def test_string_quantized_value_for_decimal(self):
+        field = serializers.DecimalField(max_digits=4, decimal_places=2)
+        value = field.to_internal_value('12').as_tuple()
+        expected_digit_tuple = (0, (1, 2, 0, 0), -2)
+        self.assertEqual(value, expected_digit_tuple)
+
+    def test_part_precision_string_quantized_value_for_decimal(self):
+        field = serializers.DecimalField(max_digits=4, decimal_places=2)
+        value = field.to_internal_value('12.0').as_tuple()
+        expected_digit_tuple = (0, (1, 2, 0, 0), -2)
+        self.assertEqual(value, expected_digit_tuple)
+
+
 class TestNoDecimalPlaces(FieldValues):
     valid_inputs = {
         '0.12345': Decimal('0.12345'),