summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRamiro Morales <cramm0@gmail.com>2011-03-03 20:56:46 +0000
committerRamiro Morales <cramm0@gmail.com>2011-03-03 20:56:46 +0000
commit3ecf628b3650e0f9f086b1ae77b43ad5df48a92e (patch)
tree03e85bb99f96bf6dadb66a0934fa81d987601aee
parent9428c2386937d0d311d5159a74b28cd309e92232 (diff)
Fixed #11206 -- Ensure that the floatformat template filter doesn't switch to scientific notation when asked to format a zero value with more than six decimal places. Thanks Tai Lee for the report and fix and Facundo Batista for his help when Decimal module expertise was needed.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@15736 bcc190cf-cafb-0310-a4f2-bffc1f526a37
-rw-r--r--django/template/defaultfilters.py14
-rw-r--r--tests/regressiontests/defaultfilters/tests.py16
2 files changed, 27 insertions, 3 deletions
diff --git a/django/template/defaultfilters.py b/django/template/defaultfilters.py
index b2aa38e50a..d923d8a0e5 100644
--- a/django/template/defaultfilters.py
+++ b/django/template/defaultfilters.py
@@ -149,9 +149,19 @@ def floatformat(text, arg=-1):
if p == 0:
exp = Decimal(1)
else:
- exp = Decimal('1.0') / (Decimal(10) ** abs(p))
+ exp = Decimal(u'1.0') / (Decimal(10) ** abs(p))
try:
- return mark_safe(formats.number_format(u'%s' % str(d.quantize(exp, ROUND_HALF_UP)), abs(p)))
+ # Avoid conversion to scientific notation by accessing `sign`, `digits`
+ # and `exponent` from `Decimal.as_tuple()` directly.
+ sign, digits, exponent = d.quantize(exp, ROUND_HALF_UP).as_tuple()
+ digits = [unicode(digit) for digit in reversed(digits)]
+ while len(digits) <= abs(exponent):
+ digits.append(u'0')
+ digits.insert(-exponent, u'.')
+ if sign:
+ digits.append(u'-')
+ number = u''.join(reversed(digits))
+ return mark_safe(formats.number_format(number, abs(p)))
except InvalidOperation:
return input_val
floatformat.is_safe = True
diff --git a/tests/regressiontests/defaultfilters/tests.py b/tests/regressiontests/defaultfilters/tests.py
index 95140b7daf..286c7f8c01 100644
--- a/tests/regressiontests/defaultfilters/tests.py
+++ b/tests/regressiontests/defaultfilters/tests.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
import datetime
-import unittest
+from django.utils import unittest
from django.template.defaultfilters import *
@@ -29,6 +29,13 @@ class DefaultFiltersTests(unittest.TestCase):
self.assertEqual(floatformat(u'¿Cómo esta usted?'), u'')
self.assertEqual(floatformat(None), u'')
+ # Check that we're not converting to scientific notation.
+ self.assertEqual(floatformat(0, 6), u'0.000000')
+ self.assertEqual(floatformat(0, 7), u'0.0000000')
+ self.assertEqual(floatformat(0, 10), u'0.0000000000')
+ self.assertEqual(floatformat(0.000000000000000000015, 20),
+ u'0.00000000000000000002')
+
pos_inf = float(1e30000)
self.assertEqual(floatformat(pos_inf), unicode(pos_inf))
@@ -46,6 +53,13 @@ class DefaultFiltersTests(unittest.TestCase):
self.assertEqual(floatformat(FloatWrapper(11.000001), -2), u'11.00')
+ # This fails because of Python's float handling. Floats with many zeroes
+ # after the decimal point should be passed in as another type such as
+ # unicode or Decimal.
+ @unittest.expectedFailure
+ def test_floatformat_fail(self):
+ self.assertEqual(floatformat(1.00000000000000015, 16), u'1.0000000000000002')
+
def test_addslashes(self):
self.assertEqual(addslashes(u'"double quotes" and \'single quotes\''),
u'\\"double quotes\\" and \\\'single quotes\\\'')