如何比较 Django 模板中的日期

Posted

技术标签:

【中文标题】如何比较 Django 模板中的日期【英文标题】:How to compare dates in Django templates 【发布时间】:2011-04-17 11:05:49 【问题描述】:

我想在 Django 中将日期与当前日期进行比较,最好在模板中进行比较,但也可以在渲染模板之前进行。如果日期已经过去,我想说“过去”,如果是将来,我想给出日期。

我希望有人可以做这样的事情:

% if listing.date <= now % 
     In the past 
% else % 
      listing.date|date:"d M Y"  
% endif %

现在是今天的日期,但这不起作用。我在 Django 文档中找不到任何关于此的内容。谁能给点建议?

【问题讨论】:

【参考方案1】:

比较视图中的日期,并将in_the_past(布尔值)之类的内容传递给extra_context。

或者最好将其作为属性添加到模型中。

from datetime import date

@property
def is_past_due(self):
    return date.today() > self.date

然后在模板中:

% if listing.is_past_due %
    In the past
% else %
     listing.date|date:"d M Y" 
% endif %

基本上,模板不是 IMO 日期比较的地方。

【讨论】:

是的,我同意模板不是日期比较的地方,但在这种情况下,它看起来要优雅得多。无论如何,我最终在我的 django 模型中实现了一个方法 inPast(),它将日期与当前日期进行比较,如果是过去则返回 True,否则返回 false。然后从模板中调用它。您的解决方案效果一样好或更好,我只是想知道模板中是否有办法做到这一点。 我不这么认为 :( 同样来自编码风格和重构 POV,最好能够在 ie 中将is_past_due 作为属性进一步复制。其他模板,否则你会有一遍又一遍地复制粘贴相同的模板代码。 如果你真的,真的,真的很想在模板中搞乱和比较日期,你必须将当前日期作为 extra_context 传递,然后使用标准的if 标签,但这不是优雅的解决方案.. 很好的解决方案!在模型中创建属性并稍后在模板中使用它们是一个很好的解决方案。毕竟从更复杂的函数的角度来看,这是一个正确的解决方案!【参考方案2】:

从 Django 1.8 开始,以下有点令人反感的结构可以完成这项工作:

% now "Y-m-d" as todays_date %
% if todays_date < someday|date:"Y-m-d" %
   <h1>It's not too late!</h1>
% endif %

Hackish,但它避免了对自定义标签或上下文处理器的需求。

【讨论】:

Dirk++; Django--【参考方案3】:

我将 date_now 添加到我的上下文处理器列表中。

所以在模板中有一个名为“date_now”的变量,它就是 datetime.datetime.now()

在文件 context_processors.py 中创建一个名为 date_now 的上下文处理器

import datetime

def date_now(request):
    return 'date_now':datetime.datetime.now()

在 settings.py 中,修改 CONTEXT_PROCESSORS 以包含它,在我的例子中是

app_name.context_processors.date_now

【讨论】:

【参考方案4】:

除了@bx2 有益的答案,如果您的字段是日期时间字段,只需调用 date() 函数来模拟日期时间字段:

from datetime import date

@property
def is_past_due(self):
    if date.today() > self.date.date():
        return True
    return False

编辑:我认为这可以缩小为:

from datetime import date

@property
def is_past_due(self):
    return date.today() > self.date.date()

【讨论】:

【参考方案5】:

我相信实现这一点的最简单方法是在您的 views.py 中导入日期时间并将今天的日期作为上下文数据传递。

context['today'] = datetime.date.today()

然后在模板标签中你可以做这样的事情。

 % if listing.date < today % 

这样,如果您将对象列表作为上下文传递,您可以在 html 模板中输出时将过滤器应用于每一行。我有一个我已经过滤掉的项目列表,并在我显示它们时使用 Bootstrap 进行风格化。我想让过期日期脱颖而出,并且仅当我的日期之一小于今天的日期时才应用过滤。

【讨论】:

【参考方案6】:

您始终可以传递 datetime.datetime.now(因为 django 模型使用 Python 的标准 datetime 对象)。

使用 render_to_response,您可以执行以下操作(在导入日期时间之后):

return render_to_response('template.html', 'now': datetime.datetime.now())

现在您可以访问模板内的“现在”,您可以像在示例中那样比较日期。

此外,如果您在视图中使用 RequestContext - 如果您在多个文件中需要它,您将能够添加“now”作为 context_processor。这会将“现在”添加到使用 RequestContext 呈现的任何模板中。

但是,更现实的是,您只需获取原始查询集中之前的记录列表,并避免首先查询无用数据:

listing.objects.filter(date__lt=datetime.datetime.now())

【讨论】:

在大多数情况下建议进行过滤,但在我的情况下,这不是预期的效果:我有一个具有特定发布日期的项目列表,我想区分已经发布的项目已发布和尚未发布,但两者都与搜索相关。出于某种原因,正如您提出的那样,“现在”变量对我不起作用。我认为问题在于 if 语句中的大于比较,显然这在所有版本的 Django 中都不可用。 您需要使用以下代码导入日期时间: import datetime 如果您使用: from datetime import datetime 那么正确的方法是 datetime.now() 而不是 datetime.datetime.now() 这个应该适用于所有版本的 django。你用的是哪个版本?【参考方案7】:

你可以有 2 个任务。

    您必须使用 DetailView 显示对象。您可以通过使用将布尔值传递给模板的函数来解决此问题。但是,请记住,在 django 中,您无法将 SQL 数据库中的日期与datetime.datetime.now() 进行比较,因为第二个选项不包含时区信息。 使用django.utils.timezone.now()。 您必须为 ListView 中的对象设置样式。然后我建议您使用将在模板中调用的自定义过滤器。
@register.filter
def compare_date(date):
   if not date:
      return False
   return date < timezone.now()

【讨论】:

【参考方案8】:

我发现了这个问题并且遇到了类似的问题。如果它只发生在过去,我正在寻找显示信息。

在模板中使用 Django 的“timesince”标签,我能够解决我的问题。我并不是说它有效,但它对我有用。

在模板中:

% if model_name.date_time|timesince >= "1 min" %
   <p>In the past</p>
% else %
   <p> model_name.date_time </p>
% endif %

【讨论】:

这甚至不推荐作为快速解决方案,因为您正在比较字符串。一天后,您正在比较 "1 day" &gt;= "1 min" 这是 False 而您期待 True

以上是关于如何比较 Django 模板中的日期的主要内容,如果未能解决你的问题,请参考以下文章

如何比较 Django 模板中的两个查询集?

如何将上下文变量与 Django 模板中的 SQL ID 进行比较?

Django模板中的Django不区分大小写字符串比较

比较 Django 模板中的 url

在 django 模板中将 str 转换为 int

带有缓存加载器的 Jinja2 与 django 模板 - 性能比较如何?