极具挑战性的查询集过滤,排序和注释(在基于Django的应用程序中)

时间:2015-11-07 00:26:13

标签: python django performance django-views django-queryset

我有一个基于Django的网络应用程序,用户可以相互聚集和聊天。我刚刚编写了一个功能,用户可以根据任何感兴趣的主题制作自己的“聊天组”。这些可以是私有,或公开可见。

我的下一个挑战是显示所有现有公共群组的列表,分页,并按最先发生的群组进行排序。经过一番深思熟虑,我认为最发生的群体是在之前 60分钟中看到最独特的访客(无声或其他)的群体。可以肯定的是,通过唯一我的意思是不同的用户,而不是同一个用户一次又一次地击中一个组。

最有效的方法是什么?在与此受欢迎列表关联的基于类的视图的get_queryset()方法中获取所需的有序查询集?其次,最有效的方法是为同一个查询集中的每个组对象注释总不同视图,这样我还可以显示总计视图,根据当前的热门排序?

相关模型是:

class Group(models.Model):
    topic = models.TextField(validators=[MaxLengthValidator(200)], null=True)
    owner = models.ForeignKey(User)
    private = models.CharField(max_length=50, default=0)
    created_at = models.DateTimeField(auto_now_add=True)

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

相关观点是:

class GroupListView(ListView):
    model = Group
    form_class = GroupListForm
    template_name = "group_list.html"
    paginate_by = 25

    def get_queryset(self):
        return Group.objects.filter(private=0,date__gte=???).distinct('grouptraffic__visitor').annotate(recent_views=Count('grouptraffic__???')).order_by('-recent_views').annotate(total_views=Count('grouptraffic__which_group=group'))

正如你所看到的,我在上面的get_queryset(self)方法中做了相当大的努力,注释了两次而没有注释。请指教!

2 个答案:

答案 0 :(得分:1)

您无法在单个django查询中合并annotate()distinct()。所以你可以尝试:

date = datetime.datetime.now()-datetime.timedelta(hours=1)

接下来的查询是获取独特访客的组合

new_traff = GroupTraffic.objects.filter(time__gte=date).distinct('visitor','which_group').values_list('id',flat=True)

trendingGrp_ids = GroupTraffic.objects.filter(id__in=new_traff).values('which_group').annotate(total=Count('which_group')).order_by('-total')

以上查询将为您提供由total订购的趋势组合,例如:

[{'total': 4, 'which_group': 2}, {'total': 2, 'which_group': 1}, {'total': 1, 'which_group': 3}]

此处total表示否。过去60分钟内每个小组的新独立访问者。

现在迭代trendingGrp_ids以获取包含视图的趋势trendingGrps:

trendingGrps = [Group.objects.filter(id=grp['which_group']).extra(select={"views":grp['total']})[0] for grp in trendingGrp_ids]

更新

获取所有公共群组,并通过衡量过去1小时内收到的流量对其进行排序。

new_traff = GroupTraffic.objects.filter(time__gte=date,which_group__private=0).distinct('visitor','which_group').values_list('id',flat=True)

trendingGrp_ids = GroupTraffic.objects.filter(id__in=new_traff).values('which_group').annotate(total=Count('which_group')).order_by('-total')

trendingGrps = [Group.objects.filter(id=grp['which_group']).extra(select={"views":grp['total']})[0] for grp in trendingGrp_ids]

trndids = [grp['which_group'] for grp in trendingGrp_ids]

nonTrendingGrps = Group.objects.filter(private=0).exclude(id__in=trndids).extra(select={"views":0})

allGrps = trendingGrps.append(nonTrendingGrps)

答案 1 :(得分:0)

1)创建一个单独的函数,用于计算聊天框中的不同视图。对于每个聊天框,将结果放在列表中。返回列表中的最大值并将其分配给变量。导入函数并使用变量过滤。

2)为每个盒子制作一套。该集包含聊天框的所有不同用户。按照集合的长度进行过滤。