【问题标题】:Highly challenging queryset filtering, sorting and annotation (in Django-based app)极具挑战性的查询集过滤、排序和注释(在基于 Django 的应用程序中)
【发布时间】:2015-11-07 00:26:12
【问题描述】:

我有一个基于 Django 的网络应用程序,用户可以在其中聚集在一起聊天。我刚刚完成了一个功能,用户可以围绕任何感兴趣的主题创建自己的“聊天组”。这些可以是私有的,也可以是公开的可见的。

我的下一个挑战是显示所有现有公共群组的列表,按最热门的群组优先进行分页和排序。经过深思熟虑后,我决定最活跃的组是在过去 60 分钟内看到最多独特访问者(沉默或其他方式)的组。可以肯定的是,我所说的唯一性是指不同的用户,而不是同一个用户一次又一次地访问一个组。

在我的基于类的视图的get_queryset() 方法中获得所需的有序查询集的最有效方法是什么?其次,最有效的方法是在同一查询集中为每个组对象添加 total distinct views 注释,以便我可以额外显示 total观看次数,同时根据当前热门进行排序?


相关模型有:

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) 方法中非常挣扎,注释了两次,什么都没有。请指教!

【问题讨论】:

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


    【解决方案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 排序的趋势 groupid,例如:

    [{'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)
    

    【讨论】:

    • 到目前为止,很好,因此接受它。如果将来有事情发生,将提出一个新问题。谢谢!
    • 所以它缺少的一件事是,它没有显示所有公共群组,它只显示了过去 60 分钟内的趋势。我实际上需要所有公共群组,按过去 60 分钟的趋势排序。
    • @HassanBaig 您如何区分黑白公共和私人团体?公共和私有组的私有字段包含什么?
    • anush,只需 group.private=='0' 选择所有公共组。另外,我尝试了一个关于诉讼程序的不同查询,一个发布在这里:stackoverflow.com/questions/33727523/…
    • 关于如何更改此 sol 以针对所有公共群体,而不仅仅是热门群体的任何消息?
    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-08
      • 1970-01-01
      • 2016-02-17
      • 1970-01-01
      • 2019-07-12
      • 1970-01-01
      相关资源
      最近更新 更多