简体   繁体   English

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

[英]Highly challenging queryset filtering, sorting and annotation (in Django-based app)

I have a Django-based web-app where users congregate and chat with one another. 我有一个基于Django的网络应用程序,用户可以在此进行聚会和聊天。 I've just finished writing a feature whereby users can make their own "chat groups", centered around any topic of interest. 我刚刚完成了一项功能,用户可以围绕任何感兴趣的主题创建自己的“聊天组”。 These could either be private , or publically visible. 这些可以是私有的 ,也可以是公开可见的。

My next challenge is showing a list of all existing public groups , paginated, and sorted by the most happening group first . 我的下一个挑战是首先列出所有现有公共团体的列表,并按发生率最高的 团体进行分页和排序。 After some deep thinking, I've decided that the most happening group is one which sees the most unique visitors (silent or otherwise) in the previous 60 mins . 经过一番深思熟虑,我决定最常发生的小组是在过去60分钟内看到最多唯一身份访问者(无论是沉默还是其他)的小组。 To be sure, by unique I mean distinct users, and not the same user hitting a group again and again. 可以肯定的是,“唯一身份”是指不同的用户,而不是同一用户一次又一次地打组。

What's the most efficient way to get the desired, ordered query-set in the get_queryset() method of my class-based view associated to this popularity listing? 在与此流行度列表相关联的基于类的视图的get_queryset()方法中,获取所需的有序查询集的最有效方法是什么? Secondly, what's the most efficient way to also annotate total distinct views to each group object in the same queryset, so that I can additionally show total views, while sort according to what's currently hot? 其次, 最有效的方法是在同一查询集中为每个组对象注释全部不同的视图 ,以便我可以同时显示全部视图,同时根据当前的热门程度进行排序?


Relevant models are: 相关模型是:

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)

The relevant view is: 相关的观点是:

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

As you can see, I've struggled rather mightily in the get_queryset(self) method above, annotating twice and what not. 如您所见,我在上面的get_queryset(self)方法中get_queryset(self)巨大的get_queryset(self) ,进行了两次注释,没有注释。 Please advise! 请指教!

You cannot combine annotate() and distinct() in a single django query. 您不能在单个django查询中组合annotate()distinct() So you can try like: 因此,您可以尝试:

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

Next query is to get the grouptraffic with unique visitors 下一个查询是获取具有唯一身份访问者的小组流量

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

The above query will get you trending groupids ordered by total like: 上面的查询将使您按total排序趋势组ID,例如:

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

Here total refers to no. 在这里total指没有。 of new unique visitors for each group in the last 60 minutes. 最近60分钟内每个组的新唯一身份访问者数量。

Now iterate over trendingGrp_ids to get the trending trendingGrps with views: 现在遍历trendingGrp_ids以获取带有视图的trendingGrpings:

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

Update: 更新:

To get all public groups, and sort them by how hot they are via measuring the traffic they received in the past 1 hr. 要获取所有公共团体,并通过测量在过去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)Create a separate function that tallies the distinct views in a chatbox. 1)创建一个单独的函数来记录聊天框中的不同视图。 For every chatbox, put the result in a list. 对于每个聊天框,将结果放在列表中。 Return the biggest value in the list and assign it to a variable. 返回列表中的最大值并将其分配给变量。 Import the function and filter with the variable. 导入函数并使用变量进行过滤。

2) Make a set for each box. 2)为每个盒子定一组。 The set contains all the distinct users of the chatbox. 该集合包含聊天框的所有不同用户。 Filter by the lenght of the set. 按设置的长度过滤。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM