如何比较 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" >= "1 min"
这是 False
而您期待 True
以上是关于如何比较 Django 模板中的日期的主要内容,如果未能解决你的问题,请参考以下文章