publik: add |clamp, |limit_low and |limit_high filters (#81223)

This commit is contained in:
Lauréline Guérin 2023-09-19 10:39:48 +02:00
parent b32771096e
commit 6e9d0a8b63
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
2 changed files with 63 additions and 1 deletions

View File

@ -99,13 +99,15 @@ def last(value):
return ''
def parse_decimal(value, default=Decimal(0)):
def parse_decimal(value, default=Decimal(0), do_raise=False):
if isinstance(value, str):
# replace , by . for French users comfort
value = value.replace(',', '.')
try:
return Decimal(value).quantize(Decimal('1.0000')).normalize()
except (ArithmeticError, TypeError):
if do_raise:
raise
return default
@ -185,6 +187,32 @@ def sum_(list_):
return ''
@register.filter
def clamp(value, minmax):
try:
value = parse_decimal(value, do_raise=True)
min_value, max_value = (parse_decimal(x, do_raise=True) for x in minmax.split())
except (ArithmeticError, TypeError, ValueError):
return ''
return max(min_value, min(value, max_value))
@register.filter
def limit_low(value, min_value):
try:
return max(parse_decimal(value, do_raise=True), parse_decimal(min_value, do_raise=True))
except (ArithmeticError, TypeError):
return ''
@register.filter
def limit_high(value, max_value):
try:
return min(parse_decimal(value, do_raise=True), parse_decimal(max_value, do_raise=True))
except (ArithmeticError, TypeError):
return ''
@register.filter(is_safe=False)
def duration(value, arg='short'):
if arg not in ('short', 'long'):

View File

@ -336,6 +336,40 @@ def test_sum():
assert t.render(Context()) == ''
def test_clamp_templatetag():
tmpl = Template('{{ value|clamp:"3.5 5.5" }}')
assert tmpl.render(Context({'value': 4})) == '4'
assert tmpl.render(Context({'value': 6})) == '5.5'
assert tmpl.render(Context({'value': 3})) == '3.5'
assert tmpl.render(Context({'value': 'abc'})) == ''
assert tmpl.render(Context({'value': None})) == ''
tmpl = Template('{{ value|clamp:"3.5 5.5 7.5" }}')
assert tmpl.render(Context({'value': 4})) == ''
tmpl = Template('{{ value|clamp:"a b" }}')
assert tmpl.render(Context({'value': 4})) == ''
def test_limit_templatetags():
for v in (3.5, '"3.5"', 'xxx'):
tmpl = Template('{{ value|limit_low:%s }}' % v)
assert tmpl.render(Context({'value': 4, 'xxx': 3.5})) == '4'
assert tmpl.render(Context({'value': 3, 'xxx': 3.5})) == '3.5'
assert tmpl.render(Context({'value': 'abc', 'xxx': 3.5})) == ''
assert tmpl.render(Context({'value': None, 'xxx': 3.5})) == ''
if v == 'xxx':
assert tmpl.render(Context({'value': 3, 'xxx': 'plop'})) == ''
tmpl = Template('{{ value|limit_high:%s }}' % v)
assert tmpl.render(Context({'value': 4, 'xxx': 3.5})) == '3.5'
assert tmpl.render(Context({'value': 3, 'xxx': 3.5})) == '3'
assert tmpl.render(Context({'value': 'abc', 'xxx': 3.5})) == ''
assert tmpl.render(Context({'value': None, 'xxx': 3.5})) == ''
if v == 'xxx':
assert tmpl.render(Context({'value': 3, 'xxx': 'plop'})) == ''
def test_duration():
context = Context({'value': 2})
assert Template('{{ value|duration }}').render(context) == '2min'