Django queryset中的跨实例计算

时间:2018-08-03 07:14:41

标签: django django-models django-queryset

如果我正确地制定任务,则不确定它是否(a)可行和(b)。也许正确的方法是重构数据库设计,但是对此我表示感谢。

我在django应用程序中有一个模型,在该模型中,我跟踪用户进入和退出某个页面的时间(通过表单提交或仅关闭浏览窗口)。我使用Django频道进行跟踪,但是在这种情况下没关系。

模型如下:

class TimeStamp(models.Model):
    class Meta:
        get_latest_by = 'enter_time'

    page_name = models.CharField(max_length=1000)
    participant = models.ForeignKey(to=Participant, related_name='timestamps')
    timestamp = models.DateTimeField()
    enter_exit_type = models.CharField(max_length=1000, choices=ENTEREXITTYPES,)

我需要做的是计算用户在此页面上花费的时间。因此,我需要遍历特定用户的Timestamp的所有记录,并计算“输入”和“退出”类型记录之间的时间差。

因此db数据可能如下所示:

id  timestamp  enter_exit_type
1  20:12:12  enter
2  20:12:13  exit
3  20:18:12  enter
4  20:21:12  exit
5  20:41:12  enter

那么生成如下结果查询集的正确方法是什么?

id  time_spent_sec  
1  0:01  
2  3:00 

最后一个“输入”记录将被忽略,因为没有相应的“退出”记录。 结果查询集中的记录1是ID 2和1中的时间戳之间的差异。结果查询集中的记录2是ID 4和3中的时间戳之间的差异。

我可以遍历记录,寻找最近的“退出”记录并进行计算,但是我在想是否有更简单的解决方案?

2 个答案:

答案 0 :(得分:1)

可能:

1)如果要在一个查询中获得所有用户的答案,请使用方法here按用户分组。

2)使用enter_exit_type == 'enter'过滤掉最后一个未关闭条目。

3).annotate(timestamp_with_sign = Case(When(enter_exit_type ='exit',then = F('timestamp') * -1),默认= F('timestamp' ),)

4)通过timestamp_with_sign字段求和。

我不确定F('timestamp')是否可以工作,您可能需要寻找将其转换为unix时间的方法。

答案 1 :(得分:0)

此模型结构可能不足以满足您的要求。所以我建议将您的模型更改为

class TimeStamp(models.Model):
    class Meta:
        get_latest_by = 'enter_time'

    page_name = models.CharField(max_length=1000)
    participant = models.ForeignKey(Musician, related_name='timestamps')
    enter = models.DateTimeField()
    exit = models.DateTimeField(null=True, blank=True)

然后您将获得数据,

from django.db.models import F, Sum, ExpressionWrapper, DurationField

TimeStamp.objects.values(
    'participant').annotate(
    sum_time_diff=Sum(
        ExpressionWrapper(F('exit') - F('enter'), output_field=DurationField())
    )
)

响应就像,

<QuerySet [{'participant': 1, 'sum_time_diff': datetime.timedelta(0, 7)}, {'participant': 2, 'sum_time_diff': datetime.timedelta(0, 2)}]>