在模板中显示和格式化 Django DurationField
Display and format Django DurationField in template
我使用的是 Django 1.8,我将我的字段之一定义为 DurationField,但我找不到任何方法在我的模板上正确显示它,如果我这样输出它:
{{runtime}}
i just get 0:00:00.007980
是否有任何过滤器或任何其他方式显示更像
的内容
2hours 30 min
不,我不认为有任何内置过滤器可以格式化 timedelta
,不过你自己写一个应该很容易。
这是一个基本示例:
from django import template
register = template.Library()
@register.filter
def duration(td):
total_seconds = int(td.total_seconds())
hours = total_seconds // 3600
minutes = (total_seconds % 3600) // 60
return '{} hours {} min'.format(hours, minutes)
这是我用的,它四舍五入,只显示需要的信息:
@register.filter
def duration(timedelta):
"""
Format a duration field
"2h and 30 min" or only "45 min" for example
:rtype: str
"""
total_seconds = int(timedelta.total_seconds())
hours = total_seconds // 3600
minutes = round((total_seconds % 3600) / 60)
if minutes == 60:
hours += 1
minutes = 0
if hours and minutes:
# Display both
return f'{hours}h and {minutes} min'
elif hours:
# Display only hours
return f'{hours}h'
# Display only minutes
return f'{minutes} min'
对 Aumo 答案的贡献:
from django import template
register = template.Library()
@register.filter
def duration(td):
total_seconds = int(td.total_seconds())
days = total_seconds // 86400
remaining_hours = total_seconds % 86400
remaining_minutes = remaining_hours % 3600
hours = remaining_hours // 3600
minutes = remaining_minutes // 60
seconds = remaining_minutes % 60
days_str = f'{days}d ' if days else ''
hours_str = f'{hours}h ' if hours else ''
minutes_str = f'{minutes}m ' if minutes else ''
seconds_str = f'{seconds}s' if seconds and not hours_str else ''
return f'{days_str}{hours_str}{minutes_str}{seconds_str}'
为了尽可能让爬虫和屏幕阅读器可读,从而提高您的 SEO 评级,最好的做法是使用 html time
标签,加上 datetime
属性。
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/time
https://www.w3.org/TR/2014/REC-html5-20141028/infrastructure.html#valid-duration-string
我已经编写了一个模板标签来完成机器和人类可读形式的持续时间格式化。这会显示天、小时、分钟、秒和微秒,使用尽可能大的增量并隐藏任何 0 值。它还处理复数化标签并根据需要添加逗号和空格。
datetime.py(模板标签文件)
import datetime
from django import template
register = template.Library()
from django.template.defaultfilters import pluralize
@register.filter
def duration(value, mode=""):
assert mode in ["machine", "phrase", "clock"]
remainder = value
response = ""
days = 0
hours = 0
minutes = 0
seconds = 0
microseconds = 0
if remainder.days > 0:
days = remainder.days
remainder -= datetime.timedelta(days=remainder.days)
if round(remainder.seconds/3600) > 1:
hours = round(remainder.seconds/3600)
remainder -= datetime.timedelta(hours=hours)
if round(remainder.seconds/60) > 1:
minutes = round(remainder.seconds/60)
remainder -= datetime.timedelta(minutes=minutes)
if remainder.seconds > 0:
seconds = remainder.seconds
remainder -= datetime.timedelta(seconds=seconds)
if remainder.microseconds > 0:
microseconds = remainder.microseconds
remainder -= datetime.timedelta(microseconds=microseconds)
if mode == "machine":
response = "P{days}DT{hours}H{minutes}M{seconds}.{microseconds}S".format(
days=days,
hours=hours,
minutes=minutes,
seconds=seconds,
microseconds=str(microseconds).zfill(6),
)
elif mode == "phrase":
response = []
if days:
response.append(
"{days} day{plural_suffix}".format(
days=days,
plural_suffix=pluralize(days),
)
)
if hours:
response.append(
"{hours} hour{plural_suffix}".format(
hours=hours,
plural_suffix=pluralize(hours),
)
)
if minutes:
response.append(
"{minutes} minute{plural_suffix}".format(
minutes=minutes,
plural_suffix=pluralize(minutes),
)
)
if seconds:
response.append(
"{seconds} second{plural_suffix}".format(
seconds=seconds,
plural_suffix=pluralize(seconds),
)
)
if microseconds:
response.append(
"{microseconds} microsecond{plural_suffix}".format(
microseconds=microseconds,
plural_suffix=pluralize(microseconds),
)
)
response = ", ".join(response)
elif mode == "clock":
response = []
if days:
response.append(
"{days} day{plural_suffix}".format(
days=days,
plural_suffix=pluralize(days),
)
)
if hours or minutes or seconds or microseconds:
time_string = "{hours}:{minutes}".format(
hours = str(hours).zfill(2),
minutes = str(minutes).zfill(2),
)
if seconds or microseconds:
time_string += ":{seconds}".format(
seconds = str(seconds).zfill(2),
)
if microseconds:
time_string += ".{microseconds}".format(
microseconds = str(microseconds).zfill(6),
)
response.append(time_string)
response = ", ".join(response)
return response
template.html(模板文件)
{% load datetime %}
<!-- phrase format -->
<time datetime="{{ event.duration|duration:'machine' }}">
{{ event.duration|duration:'phrase' }}
</time>
<!-- clock format -->
<time datetime="{{ event.duration|duration:'machine' }}">
{{ event.duration|duration:'clock' }}
</time>
示例输出
<!-- phrase format -->
<time datetime="P2DT1H0M0.000000S">2 days, 1 hour</time>
<!-- clock format -->
<time datetime="P2DT1H0M0.000000S">2 days, 01:00</time>
我使用的是 Django 1.8,我将我的字段之一定义为 DurationField,但我找不到任何方法在我的模板上正确显示它,如果我这样输出它:
{{runtime}}
i just get 0:00:00.007980
是否有任何过滤器或任何其他方式显示更像
的内容2hours 30 min
不,我不认为有任何内置过滤器可以格式化 timedelta
,不过你自己写一个应该很容易。
这是一个基本示例:
from django import template
register = template.Library()
@register.filter
def duration(td):
total_seconds = int(td.total_seconds())
hours = total_seconds // 3600
minutes = (total_seconds % 3600) // 60
return '{} hours {} min'.format(hours, minutes)
这是我用的,它四舍五入,只显示需要的信息:
@register.filter
def duration(timedelta):
"""
Format a duration field
"2h and 30 min" or only "45 min" for example
:rtype: str
"""
total_seconds = int(timedelta.total_seconds())
hours = total_seconds // 3600
minutes = round((total_seconds % 3600) / 60)
if minutes == 60:
hours += 1
minutes = 0
if hours and minutes:
# Display both
return f'{hours}h and {minutes} min'
elif hours:
# Display only hours
return f'{hours}h'
# Display only minutes
return f'{minutes} min'
对 Aumo 答案的贡献:
from django import template
register = template.Library()
@register.filter
def duration(td):
total_seconds = int(td.total_seconds())
days = total_seconds // 86400
remaining_hours = total_seconds % 86400
remaining_minutes = remaining_hours % 3600
hours = remaining_hours // 3600
minutes = remaining_minutes // 60
seconds = remaining_minutes % 60
days_str = f'{days}d ' if days else ''
hours_str = f'{hours}h ' if hours else ''
minutes_str = f'{minutes}m ' if minutes else ''
seconds_str = f'{seconds}s' if seconds and not hours_str else ''
return f'{days_str}{hours_str}{minutes_str}{seconds_str}'
为了尽可能让爬虫和屏幕阅读器可读,从而提高您的 SEO 评级,最好的做法是使用 html time
标签,加上 datetime
属性。
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/time
https://www.w3.org/TR/2014/REC-html5-20141028/infrastructure.html#valid-duration-string
我已经编写了一个模板标签来完成机器和人类可读形式的持续时间格式化。这会显示天、小时、分钟、秒和微秒,使用尽可能大的增量并隐藏任何 0 值。它还处理复数化标签并根据需要添加逗号和空格。
datetime.py(模板标签文件)
import datetime
from django import template
register = template.Library()
from django.template.defaultfilters import pluralize
@register.filter
def duration(value, mode=""):
assert mode in ["machine", "phrase", "clock"]
remainder = value
response = ""
days = 0
hours = 0
minutes = 0
seconds = 0
microseconds = 0
if remainder.days > 0:
days = remainder.days
remainder -= datetime.timedelta(days=remainder.days)
if round(remainder.seconds/3600) > 1:
hours = round(remainder.seconds/3600)
remainder -= datetime.timedelta(hours=hours)
if round(remainder.seconds/60) > 1:
minutes = round(remainder.seconds/60)
remainder -= datetime.timedelta(minutes=minutes)
if remainder.seconds > 0:
seconds = remainder.seconds
remainder -= datetime.timedelta(seconds=seconds)
if remainder.microseconds > 0:
microseconds = remainder.microseconds
remainder -= datetime.timedelta(microseconds=microseconds)
if mode == "machine":
response = "P{days}DT{hours}H{minutes}M{seconds}.{microseconds}S".format(
days=days,
hours=hours,
minutes=minutes,
seconds=seconds,
microseconds=str(microseconds).zfill(6),
)
elif mode == "phrase":
response = []
if days:
response.append(
"{days} day{plural_suffix}".format(
days=days,
plural_suffix=pluralize(days),
)
)
if hours:
response.append(
"{hours} hour{plural_suffix}".format(
hours=hours,
plural_suffix=pluralize(hours),
)
)
if minutes:
response.append(
"{minutes} minute{plural_suffix}".format(
minutes=minutes,
plural_suffix=pluralize(minutes),
)
)
if seconds:
response.append(
"{seconds} second{plural_suffix}".format(
seconds=seconds,
plural_suffix=pluralize(seconds),
)
)
if microseconds:
response.append(
"{microseconds} microsecond{plural_suffix}".format(
microseconds=microseconds,
plural_suffix=pluralize(microseconds),
)
)
response = ", ".join(response)
elif mode == "clock":
response = []
if days:
response.append(
"{days} day{plural_suffix}".format(
days=days,
plural_suffix=pluralize(days),
)
)
if hours or minutes or seconds or microseconds:
time_string = "{hours}:{minutes}".format(
hours = str(hours).zfill(2),
minutes = str(minutes).zfill(2),
)
if seconds or microseconds:
time_string += ":{seconds}".format(
seconds = str(seconds).zfill(2),
)
if microseconds:
time_string += ".{microseconds}".format(
microseconds = str(microseconds).zfill(6),
)
response.append(time_string)
response = ", ".join(response)
return response
template.html(模板文件)
{% load datetime %}
<!-- phrase format -->
<time datetime="{{ event.duration|duration:'machine' }}">
{{ event.duration|duration:'phrase' }}
</time>
<!-- clock format -->
<time datetime="{{ event.duration|duration:'machine' }}">
{{ event.duration|duration:'clock' }}
</time>
示例输出
<!-- phrase format -->
<time datetime="P2DT1H0M0.000000S">2 days, 1 hour</time>
<!-- clock format -->
<time datetime="P2DT1H0M0.000000S">2 days, 01:00</time>