如何通过相关项的条件聚合对Django查询集进行排序?

时间:2015-11-20 00:57:11

标签: python django sorting django-queryset django-orm

如何使用Django ORM通过相关项的条件聚合对查询集中的所有对象进行排序? Django 1.8及更高版本明确拥有conditional aggregation support,我需要 Django< 1.8 即可。这显然会涉及3或4个查询。以下是回答者可以用来说明她答案的示例模型:

class Group(models.Model):
    owner = models.ForeignKey(User)
    created_at = models.DateTimeField(auto_now_add=True)

class GroupTraffic(models.Model):
    visitor = models.ForeignKey(User)
    which_group = models.ForeignKey(Group)
    time_of_visit = models.DateTimeField(auto_now_add=True)

用户拥有聊天组,其他用户可以访问所述聊天组。要回答的问题是:如何生成所有组的排序列表,以便按每个组在过去60中看到的唯一流量进行排序分钟?在过去60分钟内看到大量独特访问者的群组被排序到顶部,几乎为零(或零)此类流量的群组出现在列表的底部。

这是一个条件聚合问题,因为从本质上讲,我们需要为每个组对象注释一个在过去60分钟内记录的所有相关的,唯一的grouptraffic对象的Count。

有人可以告诉我如何使用Django ORM来解决这个问题吗? 1.8?我已经知道如何通过条件聚合为> = 1.8做这件事(感谢this),我不想通过原始或额外的SQL查询来做。

1 个答案:

答案 0 :(得分:2)

只需过滤time_of_visit即可,它应该可以正常工作:

one_hour_ago = datetime.now()-timedelta(hours=1)
recent_groups = Group.objects.filter(grouptraffic__time_of_visit>=one_hour_ago)
visitors = recent_groups.annotate(views=Count('grouptraffic__visitor', distinct=True))

然后获取所有旧组,其中extra字段用于空视图:

older_groups = Group.objects.filter(grouptraffic__time_of_visit < one_hour_ago).extra(select={'visits':0})

然后将它们与管道连接起来:

all_groups = visitors | older_groups