mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	This commit is contained in:
		| @@ -126,13 +126,29 @@ def floatformat(text, arg=-1): | ||||
|     * {{ 6666.6666|floatformat:"2g" }} displays "6,666.67" | ||||
|     * {{ 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 | ||||
|     of that value. | ||||
|     """ | ||||
|     force_grouping = False | ||||
|     if isinstance(arg, str) and arg.endswith('g'): | ||||
|         force_grouping = True | ||||
|         arg = arg[:-1] or -1 | ||||
|     use_l10n = True | ||||
|     if isinstance(arg, str): | ||||
|         last_char = arg[-1] | ||||
|         if arg[-2:] in {'gu', 'ug'}: | ||||
|             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 | ||||
|     try: | ||||
|         input_val = repr(text) | ||||
|         d = Decimal(input_val) | ||||
| @@ -152,9 +168,12 @@ def floatformat(text, arg=-1): | ||||
|         return input_val | ||||
|  | ||||
|     if not m and p < 0: | ||||
|         return mark_safe( | ||||
|             formats.number_format('%d' % (int(d)), 0, force_grouping=force_grouping), | ||||
|         ) | ||||
|         return mark_safe(formats.number_format( | ||||
|             '%d' % (int(d)), | ||||
|             0, | ||||
|             use_l10n=use_l10n, | ||||
|             force_grouping=force_grouping, | ||||
|         )) | ||||
|  | ||||
|     exp = Decimal(1).scaleb(-abs(p)) | ||||
|     # Set the precision high enough to avoid an exception (#15789). | ||||
| @@ -174,9 +193,12 @@ def floatformat(text, arg=-1): | ||||
|     if sign and rounded_d: | ||||
|         digits.append('-') | ||||
|     number = ''.join(reversed(digits)) | ||||
|     return mark_safe( | ||||
|         formats.number_format(number, abs(p), force_grouping=force_grouping), | ||||
|     ) | ||||
|     return mark_safe(formats.number_format( | ||||
|         number, | ||||
|         abs(p), | ||||
|         use_l10n=use_l10n, | ||||
|         force_grouping=force_grouping, | ||||
|     )) | ||||
|  | ||||
|  | ||||
| @register.filter(is_safe=True) | ||||
|   | ||||
| @@ -1736,6 +1736,18 @@ example, when the active locale is ``en`` (English): | ||||
| ``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`` | ||||
| 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. | ||||
|  | ||||
| .. 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 | ||||
|  | ||||
| ``force_escape`` | ||||
|   | ||||
| @@ -355,7 +355,8 @@ Signals | ||||
| Templates | ||||
| ~~~~~~~~~ | ||||
|  | ||||
| * ... | ||||
| * :tfilter:`floatformat` template filter now allows using the ``u`` suffix to | ||||
|   force disabling localization. | ||||
|  | ||||
| Tests | ||||
| ~~~~~ | ||||
| @@ -574,6 +575,10 @@ Miscellaneous | ||||
|   <overriding-built-in-widget-templates>` with the appropriate template from | ||||
|   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: | ||||
|  | ||||
| Features deprecated in 4.0 | ||||
|   | ||||
| @@ -523,15 +523,15 @@ class FormattingTests(SimpleTestCase): | ||||
|             self.assertEqual('99999.999', Template('{{ f }}').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('66666.67', Template('{{ n|floatformat:2 }}').render(self.ctxt)) | ||||
|             self.assertEqual('100000.0', Template('{{ f|floatformat }}').render(self.ctxt)) | ||||
|             self.assertEqual('66666.67', Template('{{ n|floatformat:"2u" }}').render(self.ctxt)) | ||||
|             self.assertEqual('100000.0', Template('{{ f|floatformat:"u" }}').render(self.ctxt)) | ||||
|             self.assertEqual( | ||||
|                 '66666.67', | ||||
|                 Template('{{ n|floatformat:"2g" }}').render(self.ctxt), | ||||
|                 Template('{{ n|floatformat:"2gu" }}').render(self.ctxt), | ||||
|             ) | ||||
|             self.assertEqual( | ||||
|                 '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('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: | ||||
|             # thousand separator and grouping when USE_L10N is False even | ||||
|             # if the USE_THOUSAND_SEPARATOR, NUMBER_GROUPING and | ||||
|             # THOUSAND_SEPARATOR settings are specified | ||||
|             # thousand separator and grouping when localization is disabled | ||||
|             # even if the USE_THOUSAND_SEPARATOR, NUMBER_GROUPING and | ||||
|             # THOUSAND_SEPARATOR settings are specified. | ||||
|             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('100000.0', Template('{{ f|floatformat }}').render(self.ctxt)) | ||||
|                 self.assertEqual('66666.67', Template('{{ n|floatformat:"2u" }}').render(self.ctxt)) | ||||
|                 self.assertEqual('100000.0', Template('{{ f|floatformat:"u" }}').render(self.ctxt)) | ||||
|  | ||||
|     def test_false_like_locale_formats(self): | ||||
|         """ | ||||
|   | ||||
| @@ -2,7 +2,6 @@ from decimal import Decimal, localcontext | ||||
|  | ||||
| from django.template.defaultfilters import floatformat | ||||
| from django.test import SimpleTestCase | ||||
| from django.test.utils import override_settings | ||||
| from django.utils import translation | ||||
| 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.00000000000000015, 16), '1.0000000000000002') | ||||
|  | ||||
|     @override_settings(USE_L10N=True) | ||||
|     def test_force_grouping(self): | ||||
|         with translation.override('en'): | ||||
|             self.assertEqual(floatformat(10000, 'g'), '10,000') | ||||
| @@ -73,6 +71,20 @@ class FunctionTests(SimpleTestCase): | ||||
|             # Invalid suffix. | ||||
|             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): | ||||
|         self.assertEqual(floatformat(0, 6), '0.000000') | ||||
|         self.assertEqual(floatformat(0, 7), '0.0000000') | ||||
|   | ||||
		Reference in New Issue
	
	Block a user