Feature: единое отображение чисел с разделителями разрядов (фильтр ws_num)

Made-with: Cursor
This commit is contained in:
2026-02-26 15:01:08 +00:00
parent 8fcecb558d
commit 770bbbb467
9 changed files with 87 additions and 17 deletions

View File

@@ -0,0 +1 @@
# Пакет тегов и фильтров для шаблонов документов

View File

@@ -0,0 +1,53 @@
"""Фильтры для отображения чисел в шаблонах документов."""
from django import template
from decimal import Decimal
register = template.Library()
@register.filter
def ws_num(value, decimal_places=2):
"""
Форматирование числа с разделителем разрядов (неразрывный пробел)
и запятой как десятичным разделителем.
Пример: 1851635.5 -> "1 851 635,50"
"""
if value is None:
return ""
try:
places = int(decimal_places)
except (TypeError, ValueError):
places = 2
try:
if isinstance(value, (Decimal, float)):
n = float(value)
else:
n = float(value)
except (TypeError, ValueError):
return ""
if places == 0:
s = f"{int(round(n))}"
else:
s = f"{n:.{decimal_places}f}"
if "." in s:
int_part, dec_part = s.split(".", 1)
else:
int_part, dec_part = s, "0" * places
# Разделитель тысяч — неразрывный пробел
if int_part.startswith("-"):
rest = int_part[1:]
formatted = ""
while len(rest) > 3:
formatted = "\u202f" + rest[-3:] + formatted
rest = rest[:-3]
int_part = "-" + rest + formatted if rest else "-" + formatted.lstrip("\u202f")
else:
formatted = ""
rest = int_part
while len(rest) > 3:
formatted = "\u202f" + rest[-3:] + formatted
rest = rest[:-3]
int_part = (rest + formatted) if rest else formatted.lstrip("\u202f")
if places == 0:
return int_part
return f"{int_part},{dec_part}"