templatetags: manage string concatenation on add filter (#42062)
This commit is contained in:
parent
017b204bcd
commit
942afd8e9f
|
@ -1620,6 +1620,103 @@ def test_lazy_formdata_mathematics_filters(pub):
|
|||
assert tmpl.render(context) == '0.75'
|
||||
|
||||
|
||||
def test_lazy_formdata_add_filters(pub):
|
||||
formdef = FormDef()
|
||||
formdef.name = 'foobar'
|
||||
formdef.url_name = 'foobar'
|
||||
formdef.fields = [
|
||||
fields.StringField(id='0', label='term0', varname='term0'),
|
||||
fields.StringField(id='1', label='term1', varname='term1'),
|
||||
fields.StringField(id='2', label='term2', varname='term2'),
|
||||
fields.StringField(id='3', label='term3', varname='term3'),
|
||||
fields.StringField(id='4', label='term4', varname='term4'),
|
||||
]
|
||||
formdef.store()
|
||||
formdata = formdef.data_class()()
|
||||
formdata.data = {'0': 'foo', '1': '3,14', '2': '', '3': None}
|
||||
formdata.store()
|
||||
pub.substitutions.feed(formdata)
|
||||
for mode in (None, 'lazy'):
|
||||
context = pub.substitutions.get_context_variables(mode=mode)
|
||||
|
||||
# add
|
||||
tmpl = Template('{{ form_var_term1|add:form_var_term1 }}')
|
||||
assert tmpl.render(context) == '6.28'
|
||||
|
||||
tmpl = Template('{{ form_var_term1|add:form_var_term2 }}')
|
||||
assert tmpl.render(context) == '3.14'
|
||||
|
||||
tmpl = Template('{{ form_var_term1|add:form_var_term3 }}')
|
||||
assert tmpl.render(context) == '3.14'
|
||||
|
||||
tmpl = Template('{{ form_var_term1|add:form_var_term4 }}')
|
||||
assert tmpl.render(context) == '3.14'
|
||||
|
||||
tmpl = Template('{{ form_var_term2|add:form_var_term1 }}')
|
||||
assert tmpl.render(context) == '3.14'
|
||||
|
||||
tmpl = Template('{{ form_var_term3|add:form_var_term1 }}')
|
||||
assert tmpl.render(context) == '3.14'
|
||||
|
||||
tmpl = Template('{{ form_var_term4|add:form_var_term1 }}')
|
||||
assert tmpl.render(context) == '3.14'
|
||||
|
||||
# fallback to Django native add filter
|
||||
tmpl = Template('{{ form_var_term0|add:form_var_term0 }}')
|
||||
assert tmpl.render(context) == 'foofoo'
|
||||
|
||||
tmpl = Template('{{ form_var_term0|add:form_var_term1 }}')
|
||||
assert tmpl.render(context) == 'foo3,14'
|
||||
|
||||
tmpl = Template('{{ form_var_term0|add:form_var_term2 }}')
|
||||
assert tmpl.render(context) == 'foo'
|
||||
|
||||
tmpl = Template('{{ form_var_term0|add:form_var_term3 }}')
|
||||
assert tmpl.render(context) == 'foo'
|
||||
|
||||
tmpl = Template('{{ form_var_term0|add:form_var_term4 }}')
|
||||
assert tmpl.render(context) == 'foo'
|
||||
|
||||
tmpl = Template('{{ form_var_term1|add:form_var_term0 }}')
|
||||
assert tmpl.render(context) == '3,14foo'
|
||||
|
||||
tmpl = Template('{{ form_var_term2|add:form_var_term0 }}')
|
||||
assert tmpl.render(context) == 'foo'
|
||||
|
||||
tmpl = Template('{{ form_var_term2|add:form_var_term2 }}')
|
||||
assert tmpl.render(context) == ''
|
||||
|
||||
tmpl = Template('{{ form_var_term2|add:form_var_term3 }}')
|
||||
assert tmpl.render(context) == ''
|
||||
|
||||
tmpl = Template('{{ form_var_term2|add:form_var_term4 }}')
|
||||
assert tmpl.render(context) == ''
|
||||
|
||||
tmpl = Template('{{ form_var_term3|add:form_var_term0 }}')
|
||||
assert tmpl.render(context) == 'foo'
|
||||
|
||||
tmpl = Template('{{ form_var_term3|add:form_var_term2 }}')
|
||||
assert tmpl.render(context) == ''
|
||||
|
||||
tmpl = Template('{{ form_var_term3|add:form_var_term3 }}')
|
||||
assert tmpl.render(context) == ''
|
||||
|
||||
tmpl = Template('{{ form_var_term3|add:form_var_term4 }}')
|
||||
assert tmpl.render(context) == ''
|
||||
|
||||
tmpl = Template('{{ form_var_term4|add:form_var_term0 }}')
|
||||
assert tmpl.render(context) == 'foo'
|
||||
|
||||
tmpl = Template('{{ form_var_term4|add:form_var_term2 }}')
|
||||
assert tmpl.render(context) == ''
|
||||
|
||||
tmpl = Template('{{ form_var_term4|add:form_var_term3 }}')
|
||||
assert tmpl.render(context) == ''
|
||||
|
||||
tmpl = Template('{{ form_var_term4|add:form_var_term4 }}')
|
||||
assert tmpl.render(context) == ''
|
||||
|
||||
|
||||
def test_mathematic_conditions_django(pub, variable_test_data):
|
||||
for true_condition_value in (
|
||||
# reminder
|
||||
|
|
|
@ -364,11 +364,11 @@ def test_decimal_templatetag():
|
|||
def test_mathematics_templatetag():
|
||||
tmpl = Template('{{ term1|add:term2 }}')
|
||||
|
||||
# using string: convert to number or 0
|
||||
# using strings
|
||||
assert tmpl.render({'term1': '1.1', 'term2': 0}) == '1.1'
|
||||
assert tmpl.render({'term1': 'not a number', 'term2': 1.2}) == '1.2'
|
||||
assert tmpl.render({'term1': 'not a number', 'term2': 1.2}) == ''
|
||||
assert tmpl.render({'term1': 0.3, 'term2': "1"}) == '1.3'
|
||||
assert tmpl.render({'term1': 1.4, 'term2': "not a number"}) == '1.4'
|
||||
assert tmpl.render({'term1': 1.4, 'term2': "not a number"}) == ''
|
||||
|
||||
# add
|
||||
assert tmpl.render({'term1': 4, 'term2': -0.9}) == '3.1'
|
||||
|
@ -376,12 +376,37 @@ def test_mathematics_templatetag():
|
|||
assert tmpl.render({'term1': 4, 'term2': '-0.7'}) == '3.3'
|
||||
assert tmpl.render({'term1': '4', 'term2': '-0.6'}) == '3.4'
|
||||
assert tmpl.render({'term1': '', 'term2': 3.5}) == '3.5'
|
||||
assert tmpl.render({'term1': None, 'term2': 3.5}) == '3.5'
|
||||
assert tmpl.render({'term1': 3.6, 'term2': ''}) == '3.6'
|
||||
assert tmpl.render({'term1': '', 'term2': ''}) == '0'
|
||||
assert tmpl.render({'term1': '', 'term2': ''}) == ''
|
||||
assert tmpl.render({'term1': 3.6, 'term2': None}) == '3.6'
|
||||
assert tmpl.render({'term1': 0, 'term2': ''}) == '0'
|
||||
assert tmpl.render({'term1': '', 'term2': 0}) == '0'
|
||||
assert tmpl.render({'term1': 0, 'term2': 0}) == '0'
|
||||
|
||||
# add using ',' instead of '.' decimal separator
|
||||
assert tmpl.render({'term1': '1,1', 'term2': '2,2'}) == '3.3'
|
||||
assert tmpl.render({'term1': '1,1', 'term2': '2.2'}) == '3.3'
|
||||
assert tmpl.render({'term1': '1,1', 'term2': 2.2}) == '3.3'
|
||||
assert tmpl.render({'term1': '1,1', 'term2': 0}) == '1.1'
|
||||
assert tmpl.render({'term1': '1,1', 'term2': ''}) == '1.1'
|
||||
assert tmpl.render({'term1': '1,1', 'term2': None}) == '1.1'
|
||||
assert tmpl.render({'term1': '1.1', 'term2': '2,2'}) == '3.3'
|
||||
assert tmpl.render({'term1': 1.1, 'term2': '2,2'}) == '3.3'
|
||||
assert tmpl.render({'term1': 0, 'term2': '2,2'}) == '2.2'
|
||||
assert tmpl.render({'term1': '', 'term2': '2,2'}) == '2.2'
|
||||
assert tmpl.render({'term1': None, 'term2': '2,2'}) == '2.2'
|
||||
|
||||
# fallback to Django native add filter
|
||||
assert tmpl.render({'term1': 'foo', 'term2': 'bar'}) == 'foobar'
|
||||
assert tmpl.render({'term1': 'foo', 'term2': ''}) == 'foo'
|
||||
assert tmpl.render({'term1': 'foo', 'term2': None}) == 'foo'
|
||||
assert tmpl.render({'term1': '', 'term2': 'bar'}) == 'bar'
|
||||
assert tmpl.render({'term1': '', 'term2': None}) == ''
|
||||
assert tmpl.render({'term1': None, 'term2': 'bar'}) == 'bar'
|
||||
assert tmpl.render({'term1': None, 'term2': ''}) == ''
|
||||
assert tmpl.render({'term1': None, 'term2': None}) == ''
|
||||
|
||||
# subtract
|
||||
tmpl = Template('{{ term1|subtract:term2 }}')
|
||||
assert tmpl.render({'term1': 5.1, 'term2': 1}) == '4.1'
|
||||
|
|
|
@ -147,7 +147,7 @@ def time(value, arg=None):
|
|||
return defaultfilters.date(value, arg=arg)
|
||||
|
||||
|
||||
def parse_decimal(value):
|
||||
def parse_decimal(value, do_raise=False):
|
||||
if hasattr(value, 'get_value'):
|
||||
value = value.get_value() # unlazy
|
||||
if isinstance(value, six.string_types):
|
||||
|
@ -156,6 +156,8 @@ def parse_decimal(value):
|
|||
try:
|
||||
return Decimal(value).quantize(Decimal('1.0000')).normalize()
|
||||
except (ArithmeticError, TypeError):
|
||||
if do_raise:
|
||||
raise
|
||||
return Decimal(0)
|
||||
|
||||
|
||||
|
@ -277,7 +279,37 @@ def action_button(context, action_id, label, delay=3):
|
|||
@register.filter
|
||||
def add(term1, term2):
|
||||
'''replace the "add" native django filter'''
|
||||
return parse_decimal(term1) + parse_decimal(term2)
|
||||
|
||||
# consider None content as the empty string
|
||||
if term1 is None:
|
||||
term1 = ''
|
||||
if term2 is None:
|
||||
term2 = ''
|
||||
|
||||
# return available number if the other term is the empty string
|
||||
if term1 == '':
|
||||
try:
|
||||
return parse_decimal(term2, do_raise=True)
|
||||
except (ArithmeticError, TypeError):
|
||||
pass
|
||||
if term2 == '':
|
||||
try:
|
||||
return parse_decimal(term1, do_raise=True)
|
||||
except (ArithmeticError, TypeError):
|
||||
pass
|
||||
|
||||
# compute addition if both terms are numbers
|
||||
try:
|
||||
return parse_decimal(term1, do_raise=True) + parse_decimal(term2, do_raise=True)
|
||||
except (ArithmeticError, TypeError):
|
||||
pass
|
||||
|
||||
# fallback to django add filter
|
||||
if hasattr(term1, 'get_value'):
|
||||
term1 = term1.get_value() # unlazy
|
||||
if hasattr(term2, 'get_value'):
|
||||
term2 = term2.get_value() # unlazy
|
||||
return defaultfilters.add(term1, term2)
|
||||
|
||||
|
||||
@register.filter
|
||||
|
|
Loading…
Reference in New Issue