假设我们有一个事件模型:
class Event(models.Model):
actor = models.ForeignKey(Actor, null=False, blank=False, on_delete=models.PROTECT)
happened_datetime = models.DateTimeField(_('When did the event took place?'), blank=False, null=False)
和一个演员模型:
class Actor(models.Model):
name = models.CharField(_('Name'), max_length=100, blank=False, null=False, default='')
过一会儿,我们的事件清单可能会很长。
我们应该如何获取最近两个事件之间的时间间隔小于或等于指定时间增量的演员,例如:
给我所有最近活动与最近活动间隔不超过10天的演员
或
请给我所有最近活动与最近活动间隔不超过5小时的演员
一种Subquery
的发展方式吗?带有ExpressionWrapper
表达式的F
?
注意:以上查询意味着我们还应按至少引起两次事件的Actor进行过滤,其内容与此类似:
actors_with_at_least_two = Actor.objects.annotate(
nb_events=Subquery(
Event.objects.filter(
actor=OuterRef('pk')
).values(
'actor__pk'
).order_by().annotate(
cnt=Count('*')
).values('cnt')[:1],
output_field=models.IntegerField()
)
).filter(
nb_events__gte=2
)
上面的方法效果很好,但是在同一个表(timedelta等)上进行“自省”过滤很困难。任何想法/线索将不胜感激! :-)
我尝试了以下方法:
events = Event.objects.annotate(
delta_with_previous=Subquery(
Event.objects.filter(
actor=OuterRef('actor__pk')
).exclude(
pk=OuterRef('pk')
).latest(
'happened_datetime'
).values(
'actor__pk'
).order_by().values(
'happened_datetime'
)[:1],
output_field=models.DurationField
)
).filter(
delta_with_previous__lte=timedelta(days=2)
).order_by(
'actor__pk'
)
但是它似乎还不够好。