下面是我的模型结构是这样的:
class Visitor(models.Model):
id = models.AutoField(primary_key=True)
class Session(models.Model):
id = models.AutoField(primary_key=True)
visit = models.ForeignKey(Visitor)
sequence_no = models.IntegerField(null=False)
class Track(models.Model):
id = models.AutoField(primary_key=True)
session = models.ForeignKey(Session)
action = models.ForeignKey(Action)
when = models.DateTimeField(null=False, auto_now_add=True)
sequence_no = models.IntegerField(null = False)
class Action(models.Model):
id = models.AutoField(primary_key=True)
url = models.CharField(max_length=65535, null=False)
host = models.IntegerField(null=False)
正如你所看到的,每个Visitor
有多个Sessions
; 每个Session
有多个Tracks
,并且每个Track
有一个Action
。 曲目总是被递增有序session
和sequence_no
。 甲Visitors
上的位点的平均时间(即特定Action.host
)是在差Track.when
最高和最低的之间(时间) Track.sequence_no
由数除以Sessions
那的Visitor
。
我需要计算访问者的平均时间,这是时间上的每个访问者的总和在网站上Action.site
游客数除以。
我可以查询该使用SQL,但我想继续我的查询作为Djangonic越好,我仍然很失落与复杂的查询。
对于具体的Action
对象,你可以收集有关会议有趣的数据:
from django.db.models import Min, Max
from yourapp.models import *
host = 1 # I suppose you want to calculate for each site
sessions = list(Session.objects.filter(
track__action__host=host,
).annotate(
start=Min('track__when'),
end=Max('track__when'),
).values('visit_id', 'start', 'end'))
您将获得的线东西:
[
{ 'visit_id': 1, 'start': datetime(...), 'end': datetime(...) },
{ 'visit_id': 1, 'start': datetime(...), 'end': datetime(...) },
{ 'visit_id': 2, 'start': datetime(...), 'end': datetime(...) },
....
]
现在,只得到从数据中期望的结果的问题:
number_of_visitors = len(set(s['visit_id'] for s in sessions))
total_time = sum((s['end'] - s['start']).total_seconds() for s in sessions)
average_time_spent = total_time / number_of_visitors
另一种方法是使用两个查询而不是一个,并避免len(set(...))
片段:
sessions = Session.objects.filter(
track__action__host=host,
).annotate(
start=Min('track__when'),
end=Max('track__when'),
)
number_of_visitors = sessions.values('visit_id').distict().count()
total_time = sum((s['end'] - s['start']).total_seconds()
for s in sessions.values('start', 'end'))
有没有办法做实际的计算字段限制所提供的聚合,所以无论你在原始SQL做,或者你在这样的代码做。
至少提出的解决方案使用Django的ORM尽可能。