如何在Django模板中渲染DateTimeField与当前时间的时间差
核心问题说明
你的思路存在偏差,不需要将时间转换为字符串匹配格式后再计算差值,Django ORM返回的created_on本身就是datetime类型对象,可直接参与时间运算。你之前代码中将当前时间用strftime转为字符串,字符串无法和datetime对象做减法运算,自然无法计算时间差。
最优方案:使用Django内置过滤器
Django本身已经提供了timesince内置模板过滤器,可直接输出两个时间点的差值,不需要自定义实现:
<div> voted {{ vote.created_on|timesince }} ago</div>
默认输出效果为16 hours、3 days这类格式,基本符合你的需求。如果差值跨度大,内置过滤器会输出3 days, 2 hours这类多单位格式,如果你只需要保留最大单位,可使用下面的自定义过滤器实现。
自定义过滤器正确实现
如果需要自定义时间差的展示规则,可参考如下代码,同时适配Django时区设置避免类型错误,还自动处理了单复数格式:
from django import template from django.utils import timezone register = template.Library() @register.filter(name='datetime_delta') def datetime_delta(past_datetime): # 用Django内置方法获取当前时间,自动适配项目时区设置 now = timezone.now() # 统一时间的时区属性,避免时区不匹配报错 if past_datetime.tzinfo is None: past_datetime = timezone.make_aware(past_datetime) # 计算时间差 delta = now - past_datetime total_seconds = delta.total_seconds() # 按时间跨度只返回最大单位的描述,自动适配单复数 if total_seconds < 60: count = int(total_seconds) return f"{count} second" if count == 1 else f"{count} seconds" elif total_seconds < 3600: count = int(total_seconds // 60) return f"{count} minute" if count == 1 else f"{count} minutes" elif total_seconds < 86400: count = int(total_seconds // 3600) return f"{count} hour" if count == 1 else f"{count} hours" elif total_seconds < 2592000: # 30天以内按天计算 count = int(total_seconds // 86400) return f"{count} day" if count == 1 else f"{count} days" elif total_seconds < 31536000: # 1年以内按月计算 count = int(total_seconds // 2592000) return f"{count} month" if count == 1 else f"{count} months" else: count = int(total_seconds // 31536000) return f"{count} year" if count == 1 else f"{count} years"
模板使用方式和你之前的写法完全一致:
<div> voted {{ vote.created_on|datetime_delta }} ago</div>
内容的提问来源于stack exchange,提问作者JSRB
相关产品推荐
相关产品推荐

