Django QuerySet筛选器在日期\时间截止之前获取最后一个对象

Django QuerySet筛选器在日期\时间截止之前获取最后一个对象,django,Django,我试图在构建QuerySet时使其保持惰性(未评估),我的目标是找到给定日期之前的最后一个事件 class Event(models.Model): date_time = models.DateTimeField('Date and time of event') class Meta: ordering = ['-date_time'] 现在我有了截止日期和时间,我可以通过以下方式轻松获得截止日期后的所有事件: events = Event.object

我试图在构建QuerySet时使其保持惰性(未评估),我的目标是找到给定日期之前的最后一个事件

class Event(models.Model):
    date_time = models.DateTimeField('Date and time of event')

    class Meta:
         ordering = ['-date_time']
现在我有了截止日期和时间,我可以通过以下方式轻松获得截止日期后的所有事件:

events = Event.objects.filter(date_time__gte=cut_off)
现在我想把截止前的最后一个事件也包括在内

我可以想出许多方法来实现这一点,从而导致数据库命中,但我想找到一种解决方案,使QuerySet保持惰性

一个明显的候选者是窗口滞后函数。如果我们用下一个事件的日期和时间来注释这些事件,那么在概念上类似这样的事情是可行的:

window_lag = Window(expression=Lag("date_time"),
                    order_by=F("date_time").desc())

annotated_events = Event.objects.annotate(date_time_next=window_lag)
events = annotated_events.filter(date_time_next__gte=cut_off)
但遗憾的是,这还不合法:

这可以通过使用原始SQL来实现(我已经做到了),但是,哎哟。我希望尽可能地保持这一点,并且QuerySet是懒惰的(在构建它时没有数据库命中)

是否有任何创造性的方法来编写不使用窗口函数的过滤器,这些过滤器可以保持惰性,但可以实现在截止之后和截止之前返回所有事件的预期结果

我们不知道从那个事件到截止日期之间经过了多少时间,可能是几秒,可能是几年,不可能有任何假设,我们只知道,这是下一个。。就这些

可能是一种结构类似于:

events = Event.objects.filter(Q(date_time__gte=cut_off)|Q(...))

第二个Q对象以某种方式创造性地添加了所需的事件。

结果表明,单独使用Q对象是不可行的,但使用联合则是:

events = Event.objects.filter(date_time__gte=cut_off)
extra_event = Event.objects.filter(date_time__lt=cut_off)[:1]
events = events.union(extra_event)
这仍然是一个懒惰和优雅的ORM实现


我不确定这在性能方面与使用窗口滞后注释相比如何,但在Django中可过滤之前,它无论如何都不是一个优雅的ORM选项。

结果表明,仅使用Q对象是不可行的,但使用union它是:

events = Event.objects.filter(date_time__gte=cut_off)
extra_event = Event.objects.filter(date_time__lt=cut_off)[:1]
events = events.union(extra_event)
这仍然是一个懒惰和优雅的ORM实现


我不确定这与使用窗口滞后注释在性能方面的比较,但在Django中可过滤之前,它无论如何都不是一个优雅的ORM选项。

嘿,我想你可以尝试这种方法。创建另一个日期时间小于截止日期的查询集。对结果集进行相应的排序,然后选择第一条记录。一旦你有了那张唱片,你就可以把这两个问题都解决了!你会相信我在同一天晚上也有同样的顿悟,并给自己写了一张纸条来尝试吗。刚刚做了,它的工作非常出色!嘿,我想你可以试试这个方法。创建另一个日期时间小于截止日期的查询集。对结果集进行相应的排序,然后选择第一条记录。一旦你有了那张唱片,你就可以把这两个问题都解决了!你会相信我在同一天晚上也有同样的顿悟,并给自己写了一张纸条来尝试吗。刚刚做了,它的工作非常出色!