Рассчитать разницу во времени с предыдущим объектом в наборе запросов django с помощью аннотации Window - PullRequest
0 голосов
/ 12 июня 2019

В моей модели есть DateTimeField и DurationField с временем, прошедшим с последней записи, вставленной в текущую.Я пытаюсь удалить поле DurationField, но я должен быть в состоянии рассчитать время, прошедшее "на лету" ..

Этот вопрос Разница с предыдущим объектом в аннотации набора запросов django очень похожак моей проблеме.Лучший ответ предполагает использование функции Django Window, представленной в версии 2.0.Я обнаружил, что функция Lead работает только с целыми числами, но у меня есть DateTimeField, а не IntegerField, поэтому я попытался преобразовать / привести свое поле к отметке времени.

Это моя модель:

class Event(models.Model):
    date = models.DateTimeField()
    time_elapsed = models.DurationField() # TO BE REMOVED

Вот фактический набор запросов:

Event.objects
  .annotate(ts=Cast(Extract('date','epoch'),IntegerField()))
  .annotate(next_val=Window(
    expression=Lead('ts', offset=1,default=0),
    order_by=F('date').asc()),
    difference=F('next_val')-F('ts'))


Он почти работает (кажется), но он берет следующий объект и делает разницу, в то время как мне нужен PREVIOUS-объект для вычитания текущего.Я не могу найти решение для этого.

Большое спасибо!

ОБНОВЛЕНИЕ

Благодаря @radoh я нашел пропущенную функцию (Lag)К сожалению, я еще не достиг своей цели.

Здесь фактический набор запросов:

qs = Event.objects
  .annotate(ts=Cast(Extract('date','epoch'),IntegerField()))
  .annotate(prev_ts=Window(expression=Lag('ts',offset=1,default=0),order_by=F('date').asc()),
    diff=F('ts')-F('prev_ts'))

Мой diff теперь является временной дельтой (секундами между событиями) иТеперь я хотел бы исключить события со значением менее 36 часов.Я попытался перейти к прямой фильтрации цепочки () или exclude () к моему QuerySet, но кажется, что не поддерживается: -)

qs.exclude(diff__lt=129600)

ProgrammingError: оконные функциинедопустимо в WHERE

Я обнаружил, что оконные функции не разрешены, но мне интересно, есть ли другой способ сделать то, что я хочу.Есть предложения?

Спасибо

...