Django似乎在缓存datetime.now()

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

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()

0
额外
意见: 1

3 答案

不要使用 queryset 类变量,而是重写 get_queryset 。一般来说,我认为 queryset 是一个红鲱鱼。如果您只是指定 model ,Django会自动将查询集设置为 self.model.objects.all()。如果您需要任何筛选,则需要重写 get_queryset 以确保线程安全。改为尝试以下内容。

class ItemArchive(ArchiveIndexView):
    model = Item
    date_field = 'publish_date'

    def get_queryset(self):
        return super(ItemArchive, self).get_queryset().published()
0
额外

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

0
额外
感谢你们两位!它花了我一些修补,但两种解决方案都有道理。我认为dgel在我的语境中更合适。
额外 作者 user1272534,
是。或者,定义一个单独的PublishedManager,它重写 get_query_set 。这将是懒惰的,而你的发布的方法不是。
额外 作者 Daniel Roseman,
它肯定会奏效。最好的技术将取决于上下文。如果将 queryset 作为类变量真正有意义,那么Daniel的建议将是最好的。但是,如果您只是直接调用 Item.objects.published(),那么您的代码可能会更具可读性,无论您当前正在使用 queryset
额外 作者 dgel,

First, just use models.DateTimeField(auto_now_add=True)

编辑:</强>

其次,使用 get_queryset 方法:

class ItemArchive(ArchiveIndexView):
    date_field = 'publish_date'

    def get_queryset(self):
        return Item.objects.published()
0
额外
我不想使用 auto_now_add ,因为我想让用户选择编辑发布日期。覆盖 get_queryset 是dgel在他的回答中提出的建议。我认为这是解决方案。谢谢!
额外 作者 user1272534,