diff --git a/AUTHORS b/AUTHORS index 12475c2e..1d724718 100644 --- a/AUTHORS +++ b/AUTHORS @@ -242,3 +242,4 @@ that much better: * xiaost7 (https://github.com/xiaost7) * Victor Varvaryuk * Stanislav Kaledin (https://github.com/sallyruthstruik) + * Dmitry Yantsen (https://github.com/mrTable) diff --git a/docs/changelog.rst b/docs/changelog.rst index fc70f6b1..3407d9ce 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -2,6 +2,10 @@ Changelog ========= +Development +=========== +- Fixed absent rounding for DecimalField when `force_string` is set. #1103 + Changes in 0.10.8 ================= - Added support for QuerySet.batch_size (#1426) diff --git a/mongoengine/fields.py b/mongoengine/fields.py index c07a45e3..e9cc974c 100644 --- a/mongoengine/fields.py +++ b/mongoengine/fields.py @@ -341,7 +341,7 @@ class DecimalField(BaseField): if value is None: return value if self.force_string: - return unicode(value) + return unicode(self.to_python(value)) return float(self.to_python(value)) def validate(self, value): diff --git a/tests/fields/fields.py b/tests/fields/fields.py index 14b10561..6cf4f128 100644 --- a/tests/fields/fields.py +++ b/tests/fields/fields.py @@ -483,27 +483,41 @@ class FieldTest(unittest.TestCase): def test_decimal_storage(self): class Person(Document): - btc = DecimalField(precision=4) + float_value = DecimalField(precision=4) + string_value = DecimalField(precision=4, force_string=True) Person.drop_collection() - Person(btc=10).save() - Person(btc=10.1).save() - Person(btc=10.11).save() - Person(btc="10.111").save() - Person(btc=Decimal("10.1111")).save() - Person(btc=Decimal("10.11111")).save() + values_to_store = [10, 10.1, 10.11, "10.111", Decimal("10.1111"), Decimal("10.11111")] + for store_at_creation in [True, False]: + for value in values_to_store: + # to_python is called explicitly if values were sent in the kwargs of __init__ + if store_at_creation: + Person(float_value=value, string_value=value).save() + else: + person = Person.objects.create() + person.float_value = value + person.string_value = value + person.save() # How its stored - expected = [{'btc': 10.0}, {'btc': 10.1}, {'btc': 10.11}, - {'btc': 10.111}, {'btc': 10.1111}, {'btc': 10.1111}] + expected = [ + {'float_value': 10.0, 'string_value': '10.0000'}, + {'float_value': 10.1, 'string_value': '10.1000'}, + {'float_value': 10.11, 'string_value': '10.1100'}, + {'float_value': 10.111, 'string_value': '10.1110'}, + {'float_value': 10.1111, 'string_value': '10.1111'}, + {'float_value': 10.1111, 'string_value': '10.1111'}] + expected.extend(expected) actual = list(Person.objects.exclude('id').as_pymongo()) self.assertEqual(expected, actual) # How it comes out locally expected = [Decimal('10.0000'), Decimal('10.1000'), Decimal('10.1100'), Decimal('10.1110'), Decimal('10.1111'), Decimal('10.1111')] - actual = list(Person.objects().scalar('btc')) - self.assertEqual(expected, actual) + expected.extend(expected) + for field_name in ['float_value', 'string_value']: + actual = list(Person.objects().scalar(field_name)) + self.assertEqual(expected, actual) def test_boolean_validation(self): """Ensure that invalid values cannot be assigned to boolean fields.