[2.0.x] Fixed #28915 -- Prevented SQLite from truncating trailing zeros in the fractional part of DecimalField.

This reverts commit a146b65628 and adds
a test for the regression.

Backport of 6fd6d8383f from master
This commit is contained in:
Sergey Fedoseev 2017-12-12 19:07:01 +05:00 committed by Tim Graham
parent 9f39f202ab
commit 0f7ca1e878
3 changed files with 12 additions and 6 deletions

View File

@ -1,12 +1,12 @@
import datetime
import uuid
from decimal import Decimal
from django.conf import settings
from django.core.exceptions import FieldError
from django.db import utils
from django.db.backends.base.operations import BaseDatabaseOperations
from django.db.models import aggregates, fields
from django.db.models.expressions import Col
from django.utils import timezone
from django.utils.dateparse import parse_date, parse_datetime, parse_time
from django.utils.duration import duration_string
@ -208,9 +208,7 @@ class DatabaseOperations(BaseDatabaseOperations):
converters.append(self.convert_datefield_value)
elif internal_type == 'TimeField':
converters.append(self.convert_timefield_value)
# Converter for Col is added with Database.register_converter()
# in base.py.
elif internal_type == 'DecimalField' and not isinstance(expression, Col):
elif internal_type == 'DecimalField':
converters.append(self.convert_decimalfield_value)
elif internal_type == 'UUIDField':
converters.append(self.convert_uuidfield_value)
@ -241,8 +239,7 @@ class DatabaseOperations(BaseDatabaseOperations):
def convert_decimalfield_value(self, value, expression, connection):
if value is not None:
value = expression.output_field.format_number(value)
# Value is not converted to Decimal here as it will be converted
# later in BaseExpression.convert_value().
value = Decimal(value)
return value
def convert_uuidfield_value(self, value, expression, connection):

View File

@ -26,3 +26,6 @@ Bugfixes
* Corrected admin check to allow a ``OneToOneField`` in
``ModelAdmin.autocomplete_fields`` (:ticket:`28898`).
* Fixed a regression on SQLite where ``DecimalField`` returned a result with
trailing zeros in the fractional part truncated (:ticket:`28915`).

View File

@ -81,3 +81,9 @@ class DecimalFieldTests(TestCase):
expected_message = validators.DecimalValidator.messages['max_whole_digits'] % {'max': 2}
with self.assertRaisesMessage(ValidationError, expected_message):
field.clean(Decimal('999'), None)
def test_roundtrip_with_trailing_zeros(self):
"""Trailing zeros in the fractional part aren't truncated."""
obj = Foo.objects.create(a='bar', d=Decimal('8.320'))
obj.refresh_from_db()
self.assertEqual(obj.d.compare_total(Decimal('8.320')), Decimal('0'))