从Django的查询数据(Querying data from Django)

2019-10-30 00:20发布

下面是我的模型结构是这样的:

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 。 曲目总是被递增有序sessionsequence_no 。 甲Visitors上的位点的平均时间(即特定Action.host )是在差Track.when最高和最低的之间(时间) Track.sequence_no由数除以Sessions那的Visitor

我需要计算访问者的平均时间,这是时间上的每个访问者的总和在网站上Action.site游客数除以。

我可以查询该使用SQL,但我想继续我的查询作为Djangonic越好,我仍然很失落与复杂的查询。

Answer 1:

对于具体的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尽可能。



文章来源: Querying data from Django