[英]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.