如果我正确地制定任务,则不确定它是否(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中的时间戳之间的差异。
我可以遍历记录,寻找最近的“退出”记录并进行计算,但是我在想是否有更简单的解决方案?
答案 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)}]>