This commit is contained in:
parent
301a85a12f
commit
4a43335d30
|
@ -126,12 +126,28 @@ def floatformat(text, arg=-1):
|
||||||
* {{ 6666.6666|floatformat:"2g" }} displays "6,666.67"
|
* {{ 6666.6666|floatformat:"2g" }} displays "6,666.67"
|
||||||
* {{ 10000|floatformat:"g" }} displays "10,000"
|
* {{ 10000|floatformat:"g" }} displays "10,000"
|
||||||
|
|
||||||
|
If arg has the 'u' suffix, force the result to be unlocalized. When the
|
||||||
|
active locale is pl (Polish):
|
||||||
|
|
||||||
|
* {{ 66666.6666|floatformat:"2" }} displays "66666,67"
|
||||||
|
* {{ 66666.6666|floatformat:"2u" }} displays "66666.67"
|
||||||
|
|
||||||
If the input float is infinity or NaN, display the string representation
|
If the input float is infinity or NaN, display the string representation
|
||||||
of that value.
|
of that value.
|
||||||
"""
|
"""
|
||||||
force_grouping = False
|
force_grouping = False
|
||||||
if isinstance(arg, str) and arg.endswith('g'):
|
use_l10n = True
|
||||||
|
if isinstance(arg, str):
|
||||||
|
last_char = arg[-1]
|
||||||
|
if arg[-2:] in {'gu', 'ug'}:
|
||||||
force_grouping = True
|
force_grouping = True
|
||||||
|
use_l10n = False
|
||||||
|
arg = arg[:-2] or -1
|
||||||
|
elif last_char == 'g':
|
||||||
|
force_grouping = True
|
||||||
|
arg = arg[:-1] or -1
|
||||||
|
elif last_char == 'u':
|
||||||
|
use_l10n = False
|
||||||
arg = arg[:-1] or -1
|
arg = arg[:-1] or -1
|
||||||
try:
|
try:
|
||||||
input_val = repr(text)
|
input_val = repr(text)
|
||||||
|
@ -152,9 +168,12 @@ def floatformat(text, arg=-1):
|
||||||
return input_val
|
return input_val
|
||||||
|
|
||||||
if not m and p < 0:
|
if not m and p < 0:
|
||||||
return mark_safe(
|
return mark_safe(formats.number_format(
|
||||||
formats.number_format('%d' % (int(d)), 0, force_grouping=force_grouping),
|
'%d' % (int(d)),
|
||||||
)
|
0,
|
||||||
|
use_l10n=use_l10n,
|
||||||
|
force_grouping=force_grouping,
|
||||||
|
))
|
||||||
|
|
||||||
exp = Decimal(1).scaleb(-abs(p))
|
exp = Decimal(1).scaleb(-abs(p))
|
||||||
# Set the precision high enough to avoid an exception (#15789).
|
# Set the precision high enough to avoid an exception (#15789).
|
||||||
|
@ -174,9 +193,12 @@ def floatformat(text, arg=-1):
|
||||||
if sign and rounded_d:
|
if sign and rounded_d:
|
||||||
digits.append('-')
|
digits.append('-')
|
||||||
number = ''.join(reversed(digits))
|
number = ''.join(reversed(digits))
|
||||||
return mark_safe(
|
return mark_safe(formats.number_format(
|
||||||
formats.number_format(number, abs(p), force_grouping=force_grouping),
|
number,
|
||||||
)
|
abs(p),
|
||||||
|
use_l10n=use_l10n,
|
||||||
|
force_grouping=force_grouping,
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
@register.filter(is_safe=True)
|
@register.filter(is_safe=True)
|
||||||
|
|
|
@ -1736,6 +1736,18 @@ example, when the active locale is ``en`` (English):
|
||||||
``34232.00`` ``{{ value|floatformat:"-3g" }}`` ``34,232``
|
``34232.00`` ``{{ value|floatformat:"-3g" }}`` ``34,232``
|
||||||
============ ================================= =============
|
============ ================================= =============
|
||||||
|
|
||||||
|
Output is always localized (independently of the :ttag:`{% localize off %}
|
||||||
|
<localize>` tag) unless the argument passed to ``floatformat`` has the ``u``
|
||||||
|
suffix, which will force disabling localization. For example, when the active
|
||||||
|
locale is ``pl`` (Polish):
|
||||||
|
|
||||||
|
============ ================================= =============
|
||||||
|
``value`` Template Output
|
||||||
|
============ ================================= =============
|
||||||
|
``34.23234`` ``{{ value|floatformat:"3" }}`` ``34,232``
|
||||||
|
``34.23234`` ``{{ value|floatformat:"3u" }}`` ``34.232``
|
||||||
|
============ ================================= =============
|
||||||
|
|
||||||
Using ``floatformat`` with no argument is equivalent to using ``floatformat``
|
Using ``floatformat`` with no argument is equivalent to using ``floatformat``
|
||||||
with an argument of ``-1``.
|
with an argument of ``-1``.
|
||||||
|
|
||||||
|
@ -1743,6 +1755,13 @@ with an argument of ``-1``.
|
||||||
|
|
||||||
The ``g`` suffix to force grouping by thousand separators was added.
|
The ``g`` suffix to force grouping by thousand separators was added.
|
||||||
|
|
||||||
|
.. versionchanged:: 4.0
|
||||||
|
|
||||||
|
``floatformat`` template filter no longer depends on the
|
||||||
|
:setting:`USE_L10N` setting and always returns localized output.
|
||||||
|
|
||||||
|
The ``u`` suffix to force disabling localization was added.
|
||||||
|
|
||||||
.. templatefilter:: force_escape
|
.. templatefilter:: force_escape
|
||||||
|
|
||||||
``force_escape``
|
``force_escape``
|
||||||
|
|
|
@ -355,7 +355,8 @@ Signals
|
||||||
Templates
|
Templates
|
||||||
~~~~~~~~~
|
~~~~~~~~~
|
||||||
|
|
||||||
* ...
|
* :tfilter:`floatformat` template filter now allows using the ``u`` suffix to
|
||||||
|
force disabling localization.
|
||||||
|
|
||||||
Tests
|
Tests
|
||||||
~~~~~
|
~~~~~
|
||||||
|
@ -574,6 +575,10 @@ Miscellaneous
|
||||||
<overriding-built-in-widget-templates>` with the appropriate template from
|
<overriding-built-in-widget-templates>` with the appropriate template from
|
||||||
Django 3.2.
|
Django 3.2.
|
||||||
|
|
||||||
|
* The :tfilter:`floatformat` template filter no longer depends on the
|
||||||
|
:setting:`USE_L10N` setting and always returns localized output. Use the
|
||||||
|
``u`` suffix to disable localization.
|
||||||
|
|
||||||
.. _deprecated-features-4.0:
|
.. _deprecated-features-4.0:
|
||||||
|
|
||||||
Features deprecated in 4.0
|
Features deprecated in 4.0
|
||||||
|
|
|
@ -523,15 +523,15 @@ class FormattingTests(SimpleTestCase):
|
||||||
self.assertEqual('99999.999', Template('{{ f }}').render(self.ctxt))
|
self.assertEqual('99999.999', Template('{{ f }}').render(self.ctxt))
|
||||||
self.assertEqual('Des. 31, 2009', Template('{{ d }}').render(self.ctxt))
|
self.assertEqual('Des. 31, 2009', Template('{{ d }}').render(self.ctxt))
|
||||||
self.assertEqual('Des. 31, 2009, 8:50 p.m.', Template('{{ dt }}').render(self.ctxt))
|
self.assertEqual('Des. 31, 2009, 8:50 p.m.', Template('{{ dt }}').render(self.ctxt))
|
||||||
self.assertEqual('66666.67', Template('{{ n|floatformat:2 }}').render(self.ctxt))
|
self.assertEqual('66666.67', Template('{{ n|floatformat:"2u" }}').render(self.ctxt))
|
||||||
self.assertEqual('100000.0', Template('{{ f|floatformat }}').render(self.ctxt))
|
self.assertEqual('100000.0', Template('{{ f|floatformat:"u" }}').render(self.ctxt))
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
'66666.67',
|
'66666.67',
|
||||||
Template('{{ n|floatformat:"2g" }}').render(self.ctxt),
|
Template('{{ n|floatformat:"2gu" }}').render(self.ctxt),
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
'100000.0',
|
'100000.0',
|
||||||
Template('{{ f|floatformat:"g" }}').render(self.ctxt),
|
Template('{{ f|floatformat:"ug" }}').render(self.ctxt),
|
||||||
)
|
)
|
||||||
self.assertEqual('10:15 a.m.', Template('{{ t|time:"TIME_FORMAT" }}').render(self.ctxt))
|
self.assertEqual('10:15 a.m.', Template('{{ t|time:"TIME_FORMAT" }}').render(self.ctxt))
|
||||||
self.assertEqual('12/31/2009', Template('{{ d|date:"SHORT_DATE_FORMAT" }}').render(self.ctxt))
|
self.assertEqual('12/31/2009', Template('{{ d|date:"SHORT_DATE_FORMAT" }}').render(self.ctxt))
|
||||||
|
@ -628,12 +628,12 @@ class FormattingTests(SimpleTestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
# We shouldn't change the behavior of the floatformat filter re:
|
# We shouldn't change the behavior of the floatformat filter re:
|
||||||
# thousand separator and grouping when USE_L10N is False even
|
# thousand separator and grouping when localization is disabled
|
||||||
# if the USE_THOUSAND_SEPARATOR, NUMBER_GROUPING and
|
# even if the USE_THOUSAND_SEPARATOR, NUMBER_GROUPING and
|
||||||
# THOUSAND_SEPARATOR settings are specified
|
# THOUSAND_SEPARATOR settings are specified.
|
||||||
with self.settings(USE_THOUSAND_SEPARATOR=True, NUMBER_GROUPING=1, THOUSAND_SEPARATOR='!'):
|
with self.settings(USE_THOUSAND_SEPARATOR=True, NUMBER_GROUPING=1, THOUSAND_SEPARATOR='!'):
|
||||||
self.assertEqual('66666.67', Template('{{ n|floatformat:2 }}').render(self.ctxt))
|
self.assertEqual('66666.67', Template('{{ n|floatformat:"2u" }}').render(self.ctxt))
|
||||||
self.assertEqual('100000.0', Template('{{ f|floatformat }}').render(self.ctxt))
|
self.assertEqual('100000.0', Template('{{ f|floatformat:"u" }}').render(self.ctxt))
|
||||||
|
|
||||||
def test_false_like_locale_formats(self):
|
def test_false_like_locale_formats(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -2,7 +2,6 @@ from decimal import Decimal, localcontext
|
||||||
|
|
||||||
from django.template.defaultfilters import floatformat
|
from django.template.defaultfilters import floatformat
|
||||||
from django.test import SimpleTestCase
|
from django.test import SimpleTestCase
|
||||||
from django.test.utils import override_settings
|
|
||||||
from django.utils import translation
|
from django.utils import translation
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
|
|
||||||
|
@ -60,7 +59,6 @@ class FunctionTests(SimpleTestCase):
|
||||||
self.assertEqual(floatformat(1.5e-15, -20), '0.00000000000000150000')
|
self.assertEqual(floatformat(1.5e-15, -20), '0.00000000000000150000')
|
||||||
self.assertEqual(floatformat(1.00000000000000015, 16), '1.0000000000000002')
|
self.assertEqual(floatformat(1.00000000000000015, 16), '1.0000000000000002')
|
||||||
|
|
||||||
@override_settings(USE_L10N=True)
|
|
||||||
def test_force_grouping(self):
|
def test_force_grouping(self):
|
||||||
with translation.override('en'):
|
with translation.override('en'):
|
||||||
self.assertEqual(floatformat(10000, 'g'), '10,000')
|
self.assertEqual(floatformat(10000, 'g'), '10,000')
|
||||||
|
@ -73,6 +71,20 @@ class FunctionTests(SimpleTestCase):
|
||||||
# Invalid suffix.
|
# Invalid suffix.
|
||||||
self.assertEqual(floatformat(10000, 'g2'), '10000')
|
self.assertEqual(floatformat(10000, 'g2'), '10000')
|
||||||
|
|
||||||
|
def test_unlocalize(self):
|
||||||
|
with translation.override('de', deactivate=True):
|
||||||
|
self.assertEqual(floatformat(66666.666, '2'), '66666,67')
|
||||||
|
self.assertEqual(floatformat(66666.666, '2u'), '66666.67')
|
||||||
|
with self.settings(
|
||||||
|
USE_THOUSAND_SEPARATOR=True,
|
||||||
|
NUMBER_GROUPING=3,
|
||||||
|
THOUSAND_SEPARATOR='!',
|
||||||
|
):
|
||||||
|
self.assertEqual(floatformat(66666.666, '2gu'), '66!666.67')
|
||||||
|
self.assertEqual(floatformat(66666.666, '2ug'), '66!666.67')
|
||||||
|
# Invalid suffix.
|
||||||
|
self.assertEqual(floatformat(66666.666, 'u2'), '66666.666')
|
||||||
|
|
||||||
def test_zero_values(self):
|
def test_zero_values(self):
|
||||||
self.assertEqual(floatformat(0, 6), '0.000000')
|
self.assertEqual(floatformat(0, 6), '0.000000')
|
||||||
self.assertEqual(floatformat(0, 7), '0.0000000')
|
self.assertEqual(floatformat(0, 7), '0.0000000')
|
||||||
|
|
Loading…
Reference in New Issue