【问题标题】:Django seems to be caching datetime.now()Django 似乎正在缓存 datetime.now()
【发布时间】:2012-05-24 16:05:55
【问题描述】:

我有一个看起来像这样的模型:

class Item(models.Model):
    ...
    publish_date = models.DateTimeField(default=datetime.datetime.now)
    ...

还有一个看起来像这样的经理:

from datetime import datetime

class ItemManager(Manager):
    def published(self):
        return self.get_query_set().filter(publish_date__lte=datetime.now()

还有一个看起来像这样的视图:

class ItemArchive(ArchiveIndexView):
    queryset = Item.objects.published()
    date_field = 'publish_date'

我的想法是我可以调用Item.objects.published() 并获取所有已发布Items 的查询集。

问题是 Django 似乎在服务器启动时在管理器中执行datetime.now() 调用,然后缓存该值。因此,如果今天是 5 月 24 日,我创建了一个发布日期为 5 月 23 日的 Item,并在 5 月 22 日启动了服务器,那么 5 月 23 日的项目将不会显示在 ItemArchive 视图中。一旦我重新启动 Apache,5 月 23 日的项目就会正确显示在视图中。

如何在每次调用经理时强制 Django 执行datetime.now()

【问题讨论】:

    标签: python django caching datetime


    【解决方案1】:

    我相信这是由您将queryset = Item.objects.published() 定义为类变量的视图引起的。当您的 ItemArchive 类最初被导入时,这一行将被执行一次。您应该将该行移到每次调用视图时都会执行的方法中。

    【讨论】:

    • 是的。或者,定义一个单独的 PublishedManager,它会覆盖 get_query_set。这将是懒惰的,而您的 published 方法不是。
    • 它肯定会起作用。最好的技术将取决于上下文。如果将queryset 作为类变量确实有意义,那么丹尼尔的建议将是最好的。但是,如果您在当前使用queryset 的任何地方直接调用Item.objects.published(),您的代码可能更具可读性。
    • 谢谢你们!我花了一些时间修修补补,但这两种解决方案都很有意义。我认为 dgel 更适合我的情况。
    【解决方案2】:

    不要使用queryset 类变量,而是覆盖get_queryset。总的来说,我认为queryset 有点像红鲱鱼。如果您只是指定model,Django 会自动将查询集设置为self.model.objects.all()。如果您需要任何过滤,100 次中有 99 次需要覆盖 get_queryset 以保证线程安全。请尝试以下方法。

    class ItemArchive(ArchiveIndexView):
        model = Item
        date_field = 'publish_date'
    
        def get_queryset(self):
            return super(ItemArchive, self).get_queryset().published()
    

    【讨论】:

      【解决方案3】:

      首先,只需使用models.DateTimeField(auto_now_add=True)

      已编辑:

      二、使用get_queryset方法:

      class ItemArchive(ArchiveIndexView):
          date_field = 'publish_date'
      
          def get_queryset(self):
              return Item.objects.published()
      

      【讨论】:

      • 我不想使用auto_now_add,因为我想让用户选择编辑发布日期。覆盖get_queryset 是 dgel 在他的回答中建议的。我认为这就是解决方案。谢谢!
      猜你喜欢
      • 2016-11-26
      • 1970-01-01
      • 1970-01-01
      • 2013-05-27
      • 1970-01-01
      • 2013-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多