【问题标题】:Querying data from Django从 Django 查询数据
【发布时间】:2011-08-05 10:14:37
【问题描述】:

这是我的模型结构的样子:

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.sequence_no 之间的Track.when(时间)的差异除以VisitorSessions 的数量。

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

我可以使用 SQL 进行查询,但我希望我的查询尽可能使用 Djangonic,但我仍然对复杂的查询感到很困惑。

【问题讨论】:

    标签: django django-models django-queryset


    【解决方案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(...)) sn-p:

    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。

    【讨论】:

      猜你喜欢
      • 2018-03-03
      • 1970-01-01
      • 2022-01-05
      • 1970-01-01
      • 1970-01-01
      • 2013-12-18
      • 2018-04-08
      • 2019-03-30
      相关资源
      最近更新 更多