add new templatetags logic for date, datetime, time, decimal (#28738)

This commit is contained in:
Thomas NOËL 2018-12-07 10:39:29 +01:00
parent 0e02e4be5b
commit 5015a0f9ea
2 changed files with 145 additions and 10 deletions

View File

@ -110,6 +110,94 @@ def test_template_encoding():
def test_datetime_templatetags():
tmpl = Template('{{ plop|datetime }}')
assert tmpl.render({'plop': '2017-12-21 10:32'}) == 'Dec. 21, 2017, 10:32 a.m.'
assert tmpl.render({'plop': '21/12/2017 10h32'}) == 'Dec. 21, 2017, 10:32 a.m.'
assert tmpl.render({'plop': '2017-12-21'}) == 'Dec. 21, 2017, midnight'
assert tmpl.render({'plop': '21/12/2017'}) == 'Dec. 21, 2017, midnight'
assert tmpl.render({'plop': '10h32'}) == ''
assert tmpl.render({'plop': 'x'}) == ''
assert tmpl.render({'plop': None}) == ''
assert tmpl.render({'plop': 3}) == ''
assert tmpl.render({'plop': {'foo': 'bar'}}) == ''
assert tmpl.render() == ''
tmpl = Template('{{ plop|datetime:"d i" }}')
assert tmpl.render({'plop': '2017-12-21 10:32'}) == '21 32'
assert tmpl.render({'plop': '2017-12-21 10:32:42'}) == '21 32'
assert tmpl.render({'plop': '21/12/2017 10:32'}) == '21 32'
assert tmpl.render({'plop': '21/12/2017 10:32:42'}) == '21 32'
assert tmpl.render({'plop': '21/12/2017 10h32'}) == '21 32'
assert tmpl.render({'plop': '21/12/2017'}) == '21 00'
assert tmpl.render({'plop': '10h32'}) == ''
assert tmpl.render({'plop': 'x'}) == ''
assert tmpl.render({'plop': None}) == ''
assert tmpl.render({'plop': 3}) == ''
assert tmpl.render({'plop': {'foo': 'bar'}}) == ''
assert tmpl.render() == ''
tmpl = Template('{% if d1|datetime > d2|datetime %}d1>d2{% else %}d1<=d2{% endif %}')
assert tmpl.render({'d1': '2017-12-22', 'd2': '2017-12-21'}) == 'd1>d2'
assert tmpl.render({'d1': '2017-12-21', 'd2': '2017-12-21'}) == 'd1<=d2'
assert tmpl.render({'d1': '2017-12-21 10:30', 'd2': '2017-12-21 09:00'}) == 'd1>d2'
assert tmpl.render({'d1': '2017-12-21 10:30', 'd2': '2017-12-21'}) == 'd1>d2'
assert tmpl.render({'d1': '2017-12-22'}) == 'd1<=d2'
assert tmpl.render({'d2': '2017-12-22'}) == 'd1<=d2'
tmpl = Template('{{ plop|date }}')
assert tmpl.render({'plop': '2017-12-21'}) == 'Dec. 21, 2017'
assert tmpl.render({'plop': '21/12/2017'}) == 'Dec. 21, 2017'
assert tmpl.render({'plop': '2017-12-21 10:32'}) == 'Dec. 21, 2017'
assert tmpl.render({'plop': '21/12/2017 10:32'}) == 'Dec. 21, 2017'
assert tmpl.render({'plop': '21/12/2017 10h32'}) == 'Dec. 21, 2017'
assert tmpl.render({'plop': '21/12/2017 10:32:42'}) == 'Dec. 21, 2017'
assert tmpl.render({'plop': '10:32'}) == ''
assert tmpl.render({'plop': 'x'}) == ''
assert tmpl.render({'plop': None}) == ''
assert tmpl.render({'plop': 3}) == ''
assert tmpl.render({'plop': {'foo': 'bar'}}) == ''
assert tmpl.render() == ''
tmpl = Template('{{ plop|date:"d" }}')
assert tmpl.render({'plop': '2017-12-21'}) == '21'
assert tmpl.render({'plop': '21/12/2017'}) == '21'
assert tmpl.render({'plop': '2017-12-21 10:32'}) == '21'
assert tmpl.render({'plop': '10:32'}) == ''
assert tmpl.render({'plop': 'x'}) == ''
assert tmpl.render({'plop': None}) == ''
assert tmpl.render({'plop': 3}) == ''
assert tmpl.render({'plop': {'foo': 'bar'}}) == ''
assert tmpl.render() == ''
tmpl = Template('{% if d1|date > d2|date %}d1>d2{% else %}d1<=d2{% endif %}')
assert tmpl.render({'d1': '2017-12-22', 'd2': '2017-12-21'}) == 'd1>d2'
assert tmpl.render({'d1': '2017-12-21', 'd2': '2017-12-21'}) == 'd1<=d2'
assert tmpl.render({'d1': '2017-12-22'}) == 'd1<=d2'
assert tmpl.render({'d2': '2017-12-22'}) == 'd1<=d2'
tmpl = Template('{{ plop|time }}')
assert tmpl.render({'plop': '10:32'}) == '10:32 a.m.'
assert tmpl.render({'plop': '2017-12-21 10:32'}) == '10:32 a.m.'
assert tmpl.render({'plop': '21/12/2017 10h32'}) == '10:32 a.m.'
assert tmpl.render({'plop': '21/12/2017'}) == 'midnight'
assert tmpl.render({'plop': 'x'}) == ''
assert tmpl.render({'plop': None}) == ''
assert tmpl.render({'plop': 3}) == ''
assert tmpl.render({'plop': {'foo': 'bar'}}) == ''
assert tmpl.render() == ''
tmpl = Template('{{ plop|time:"H i" }}')
assert tmpl.render({'plop': '10:32'}) == '10 32'
assert tmpl.render({'plop': '2017-12-21 10:32'}) == '10 32'
assert tmpl.render({'plop': '21/12/2017 10h32'}) == '10 32'
assert tmpl.render({'plop': '21/12/2017'}) == '00 00'
assert tmpl.render({'plop': 'x'}) == ''
assert tmpl.render({'plop': None}) == ''
assert tmpl.render({'plop': 3}) == ''
assert tmpl.render({'plop': {'foo': 'bar'}}) == ''
assert tmpl.render() == ''
# old fashion, with parse_*
tmpl = Template('{{ plop|parse_datetime|date:"d i" }}')
assert tmpl.render({'plop': '2017-12-21 10:32'}) == '21 32'
assert tmpl.render({'plop': '2017-12-21 10:32:42'}) == '21 32'
@ -152,7 +240,20 @@ def test_decimal_templatetag():
assert tmpl.render({'plop': 12345.678}) == '12345.678'
assert tmpl.render({'plop': None}) == ''
tmpl = Template('{{ plop|decimal:3 }}')
assert tmpl.render({'plop': '3.14'}) == '3.140'
assert tmpl.render({'plop': None}) == ''
tmpl = Template('{{ plop|decimal:"3" }}')
assert tmpl.render({'plop': '3.14'}) == '3.140'
assert tmpl.render({'plop': None}) == ''
tmpl = Template('{% if plop|decimal > 2 %}hello{% endif %}')
assert tmpl.render({'plop': 3}) == 'hello'
assert tmpl.render({'plop': '3'}) == 'hello'
assert tmpl.render({'plop': 2.001}) == 'hello'
assert tmpl.render({'plop': '2.001'}) == 'hello'
assert tmpl.render({'plop': 1}) == ''
assert tmpl.render({'plop': 1.99}) == ''
assert tmpl.render({'plop': '1.99'}) == ''
assert tmpl.render({'plop': 'x'}) == 'hello'
assert tmpl.render({'plop': None}) == 'hello' # will be str > int, always True.

View File

@ -51,6 +51,14 @@ def parse_date(date_string):
except (ValueError, TypeError):
return None
@register.filter(expects_localtime=True, is_safe=False)
def date(value, arg=None):
if arg is None:
return parse_date(value) or ''
if not isinstance(value, (datetime.datetime, datetime.date, datetime.time)):
value = parse_datetime(value) or parse_date(value)
return defaultfilters.date(value, arg=arg)
@register.filter
def parse_datetime(datetime_string):
try:
@ -63,30 +71,56 @@ def parse_datetime(datetime_string):
except (ValueError, TypeError):
return None
@register.filter(name='datetime', expects_localtime=True, is_safe=False)
def datetime_(value, arg=None):
if arg is None:
return parse_datetime(value) or ''
if not isinstance(value, (datetime.datetime, datetime.date, datetime.time)):
value = parse_datetime(value)
return defaultfilters.date(value, arg=arg)
@register.filter
def parse_time(time_string):
# if input is a datetime, extract its time
try:
dt = parse_datetime(time_string)
if dt:
return dt.time()
except (ValueError, TypeError):
pass
# fallback to Django function
try:
return dateparse.parse_time(time_string)
except (ValueError, TypeError):
return None
@register.filter(expects_localtime=True, is_safe=False)
def date(value, arg=None):
def time(value, arg=None):
if arg is None:
parsed = parse_time(value)
return parsed if parsed is not None else '' # because bool(midnight) == False
if not isinstance(value, (datetime.datetime, datetime.date, datetime.time)):
value = parse_date(value)
value = parse_time(value)
return defaultfilters.date(value, arg=arg)
@register.filter(is_safe=True)
def decimal(value):
def parse_decimal(value):
if not value:
return ''
return None
if isinstance(value, basestring):
# replace , by . for French users comfort
value = value.replace(',', '.')
try:
if isinstance(value, basestring):
# replace , by . for French users comfort
value = value.replace(',', '.')
return Decimal(value).quantize(Decimal('1.0000')).normalize()
except ArithmeticError:
return ''
except (ArithmeticError, TypeError):
return None
@register.filter(is_safe=True)
def decimal(value, arg=None):
if arg is None:
return parse_decimal(value) or ''
if not isinstance(value, Decimal):
value = parse_decimal(value)
return defaultfilters.floatformat(value, arg=arg)
@register.simple_tag
def standard_text(text_id):