【问题标题】:Using datetime.now() in Django view在 Django 视图中使用 datetime.now()
【发布时间】:2016-10-05 03:58:28
【问题描述】:

守则

我在 Django 视图中使用 datetime.now() 作为过滤器的一部分,如下所示:

def get_now():
    return timezone.now()

class BulletinListView(ListView):
    model = Announcement
    template_name = 'newswire/home.html'

    def get_context_data(self, **kwargs):
        context = super(BulletinListView, self).get_context_data(**kwargs)

        try:
            published_announcements = Announcement.objects.filter(publish_start_date__lte=get_now(), publish_end_date__gte=get_now()).filter(hidden=False, under_review=False).extra(order_by=['-publish_start_date', 'publish_end_date'])
        except Announcement.DoesNotExist:
            published_announcements = None

        if published_announcements is not None:
            context['announcements'] = published_announcements
            max_print_annoucements = int(config.MAX_PRINT_ANNOUCEMENTS)
            context['announcements_print'] = published_announcements[
                :max_print_annoucements]
            context['more_annoucements_online_count'] = published_announcements.count() - max_print_annoucements

        return context

编辑:设法更新并包含更多代码

它可以正常工作并根据datetime.now()提供的日期获取应该发布且未被隐藏或正在审查的公告

问题

我使用datetime.datetime.now() 过滤掉旧公告,但在生产环境中经过一天后我意识到datetime.datetime.now() 仅在服务器启动时才被评估,并且每次调用视图时值都不会更新,这导致第二天到来时过滤错误的数据。这也影响了另一个检索未来 7 天内即将到来的生日的函数。

我阅读和尝试过的事情

我看到了许多关于使用可调用 datetime.now 而不是 datetime.now() 的问题,但仅限于在模型中设置默认值的情况下。

我已经定义了一个如下的函数,认为它会强制 datetime.now 再次被评估,但它似乎不起作用。

def get_now():
    return timezone.now())

当我通过日期进入上下文以查看我得到了什么时,我发现日期和时间并没有超过我部署服务器的时间。

我在视图中看到了许多使用 datetime.now() 的示例,但没有一个遇到此问题。

我怀疑我在开发中从未见过这种情况,因为我使用 --reload 选项运行开发 gunicorn 服务器,并且在我保存更改并重新启动服务器时不断评估 datetime.now()

This problem 似乎很相似,但我不确定它与我的情况有何相似/不同

上下文:

我正在编写一个 Django 应用程序,我的开发和生产环境是使用 docker 实现的,应用程序在 nginx 代理后面运行

/usr/local/bin/gunicorn app.wsgi:application -w 2 -b :8000

【问题讨论】:

  • "但是在生产环境中经过一天后我意识到 datetime.datetime.now() 仅在服务器启动时才被评估,并且每次调用视图时值都不会更新"不是这样.你可能有一个混乱的缓存设置
  • 顺便说一句,可能跨时区处理请求的服务器应该通过datetime.utcnow() 使用世界时。
  • @e4c5 我将再次查看堆栈是否有任何缓存,但从我的 Django 设置文件中我没有定义任何缓存。
  • @tdelaney 感谢您指出这一点,在为我的问题寻找答案后,我也意识到了这一点,并希望将事情转移过来。我最终将使用datetime.utcnow(),顺便说一句,我正在从事另一个时区的这个项目!所以时区的事情对我来说有点真实。我正在慢慢弄清楚,第一个Django项目!第一个具有真实用户反馈的真实世界应用程序。
  • 尝试在不同的浏览器中打开(我推荐使用隐身模式),看看你是否得到不同的结果。视图应该工作。它可以缓存在浏览器或中间网络硬件的某个位置。

标签: python django datetime gunicorn


【解决方案1】:

每次调用视图时该值都不会更新 在第二天到来时过滤错误的数据

你必须决定你说的是哪个“第二天”?是吗:

  1. 访问您网站的用户的第二天。
  2. 第二天为您访问该网站。
  3. 服务器上设置的时区的第二天。

每一个都会导致“错误”的结果,而实际上代码并没有什么问题。

这是因为您的代码在时区方面过于幼稚。它基本上完全忽略了时区。

这是一个复杂的话题,django 有一个complete section of the manual 专门用于处理时区。我建议阅读一两次,因为时区会以多种方式影响您的网站。

最后,您可以稍微清理一下代码,如下所示:

try:
   max_print_annoucements = int(config.MAX_PRINT_ANNOUCEMENTS)
except ValueError:
   max_print_announcements = 0

published_announcements = Announcement.objects.filter(publish_start_date__lte=get_now(),
                                                      publish_end_date__gte=get_now())
                                              .filter(hidden=False, under_review=False)
                                              .extra(order_by=['-publish_start_date',
                                                               'publish_end_date'])

context['announcements'] = published_announcements
context['announcements_print'] = published_announcements[:max_print_annoucements]
context['more_annoucements_online_count'] = abs(published_announcements.count() - max_print_annoucements)

【讨论】:

  • “当第二天到来”字面意思是当我在第二天加载页面时, datetime.now() 应该真正反映当前日期/时间,但它仍然是我部署的时间容器投入生产。我实际上不认为这个问题与时区有任何关系。我做了context['now'] = get_now() 并使用{{ now|date:"l g:i A, j F o" }} 在模板中显示它,它表明日期/时间基本上只是在我在生产中部署服务器时卡住了。这样做有什么问题吗?
  • 除非服务器正在运行您的本地计算机,否则您的第二天和服务器的第二天可能会有所不同。
猜你喜欢
  • 2013-07-31
  • 2015-04-11
  • 2019-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-15
  • 2021-02-04
相关资源
最近更新 更多