【发布时间】:2020-07-17 11:47:06
【问题描述】:
我们有一个表格,其中包含多个事件以及添加事件的时间。用于存储事件的默认时区是 UTC。例如:
class Events:
type = models.CharField(max_length=45, null=False)
date_added = models.DateTimeField(auto_now_add=True)
现在,我们想要获取两个日期之间不同事件类型的每日计数 - start_date 和 end_date。例如:对于 start_date = "2020-03-1" 和 end_date = "2020-03-31",输出应该是 -
[{
"date" : "2020-03-1",
"event1" : 200,
"event2" : 606,
"event3" : 595
},
{
"date" : "2020-03-2",
"event1" : 357,
"event2" : 71,
"event3" : 634
},
{
"date" : "2020-03-3",
"event1" : 106,
"event2" : 943,
"event3" : 315
},
{
"date" : "2020-03-4",
"event1" : 187,
"event2" : 912,
"event3" : 743
},
.
.
.
.
{
"date" : "2020-03-31",
"event1" : 879,
"event2" : 292,
"event3" : 438
}]
由于用户位于不同的时区(美国、欧洲、亚洲等),我们希望在计算事件之前根据用户转换时区。以 UTC 计数在用户的时区中每天都会有错误的计数。例如:创建于 3 月 3 日凌晨 1:30 IST 的事件将在 3 月 2 日晚上 8 点(UTC 时间)显示并相应计数。
如果我们使用 for 循环,它会变得非常昂贵。因此,我们希望使用 Django ORM 在 DB 级别进行操作。如果不可能完全依赖 Django ORM,我们希望使其尽可能高效。
我们能想到的最好的查询是:
Events.objects.filter(
pk = user_pk, date__range = (
(end_date - time_delta).strftime("%Y-%m-%d"),
end_date.strftime("%Y-%m-%d")
)
).extra({
"date_added" : "date(date_added)"
}).values(
"date_added",
"type"
).annotate(
models.Count("type")
)
我们得到的结果如下:
<QuerySet [{'date_added': datetime.date(2020, 3, 6), 'type': 'event1', 'type__count': 30},
{'date_added': datetime.date(2020, 3, 6), 'type': 'event2', 'type__count': 189},
{'date_added': datetime.date(2020, 3, 6), 'type': 'event3', 'type__count': 1},
{'date_added': datetime.date(2020, 3, 6), 'type': 'event4', 'type__count': 3},
{'date_added': datetime.date(2020, 3, 9), 'type': 'event2', 'type__count': 57},
{'date_added': datetime.date(2020, 3, 9), 'type': 'event1', 'type__count': 23},
{'date_added': datetime.date(2020, 3, 9), 'type': 'event4', 'type__count': 1},
{'date_added': datetime.date(2020, 3, 10), 'type': 'event1', 'type__count': 5},
{'date_added': datetime.date(2020, 3, 10), 'type': 'event2', 'type__count': 21},
{'date_added': datetime.date(2020, 3, 11), 'type': 'event2', 'type__count': 9},
{'date_added': datetime.date(2020, 3, 11), 'type': 'event1', 'type__count': 15},
{'date_added': datetime.date(2020, 3, 12), 'type': 'event2', 'type__count': 49},
{'date_added': datetime.date(2020, 3, 13), 'type': 'event2', 'type__count': 8},
{'date_added': datetime.date(2020, 3, 13), 'type': 'event1', 'type__count': 3},
{'date_added': datetime.date(2020, 3, 17), 'type': 'event1', 'type__count': 16},
{'date_added': datetime.date(2020, 3, 17), 'type': 'event2', 'type__count': 26},
{'date_added': datetime.date(2020, 3, 17), 'type': 'event4', 'type__count': 1},
{'date_added': datetime.date(2020, 3, 17), 'type': 'event3', 'type__count': 1},
{'date_added': datetime.date(2020, 3, 18), 'type': 'event2', 'type__count': 64},
{'date_added': datetime.date(2020, 3, 18), 'type': 'event1', 'type__count': 11},
'...(remaining elements truncated)...']>
这仍然需要一个 for 循环来将具有相同日期的所有事件添加到一个字典中,但时区问题仍然存在。
如何解决?
【问题讨论】:
标签: python django django-models mysql-python django-timezone