如何在Django模板中比较timeuntil与特定时间间隔?
解决Django中文章NEW标签显示的问题
嘿,我明白你遇到的问题了!你用timeuntil过滤器和数字比较的思路走不通,是因为**timeuntil返回的是字符串**(比如“1天”“2小时”这种人类可读的格式),不是数值类型,所以和数字2直接比较根本不会得到你想要的结果。
下面给你几种靠谱的解决方法,按推荐程度排序:
方法一:在视图层计算布尔值(最推荐)
把判断逻辑放在视图里,模板只负责展示,这样代码更清晰,也符合Django“胖模型/视图,瘦模板”的理念。
比如在你的视图里(比如ListView或者DetailView):
from datetime import timedelta from django.utils import timezone # 如果是列表视图,遍历文章添加标记 def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) for article in context['articles']: # 判断是否是2天内发布的,改成hours=2就是2小时内 article.is_new = timezone.now() - article.created_at < timedelta(days=2) return context # 如果是单篇文章视图,直接给对象加属性 def get_object(self, queryset=None): article = super().get_object(queryset=queryset) article.is_new = timezone.now() - article.created_at < timedelta(hours=2) return article
然后模板里直接用这个预计算好的布尔值:
{% if article.is_new %} <span class="label label-new">NEW</span> {% endif %}
方法二:模板内直接比较时间(无需修改视图)
如果你不想改视图,可以在模板里给创建时间加上指定间隔,再和当前时间比较。记得先加载时区标签,避免时区问题:
{% load tz %} {# 判断是否是2天内发布的 #} {% if article.created_at|add:"2 days" > timezone.now %} <span class="label label-new">NEW</span> {% endif %} {# 如果是2小时内,就改成add:"2 hours" #} {% if article.created_at|add:"2 hours" > timezone.now %} <span class="label label-new">NEW</span> {% endif %}
方法三:自定义模板过滤器(灵活扩展)
如果需要在多个模板里复用这个逻辑,可以写一个自定义过滤器。
- 在你的app目录下创建
templatetags文件夹(如果没有的话),里面新建custom_filters.py文件:
from django import template from datetime import timedelta from django.utils import timezone register = template.Library() @register.filter(name='is_new') def is_new(publish_time, interval_str): # 支持传入类似"2 days"或"2 hours"的参数 try: value, unit = interval_str.split() delta = timedelta(**{unit: int(value)}) return timezone.now() - publish_time < delta except (ValueError, TypeError): return False
- 在模板里加载这个过滤器并使用:
{% load custom_filters %} {# 判断2天内的文章 #} {% if article.created_at|is_new:"2 days" %} <span class="label label-new">NEW</span> {% endif %} {# 判断2小时内的文章 #} {% if article.created_at|is_new:"2 hours" %} <span class="label label-new">NEW</span> {% endif %}
为什么原来的代码无效?
再强调下:timeuntil过滤器的返回值是格式化后的字符串,比如当文章发布1小时前,它返回的是"1小时",而不是数字1。你拿字符串和数字2比较,在Django模板里会被当成不相等的情况,所以永远不会显示NEW标签。
内容的提问来源于stack exchange,提问作者Hyeonseo Kim
相关产品推荐
相关产品推荐

