Python django中列表列表的排序和计数元素
我有Python django中列表列表的排序和计数元素,python,django,python-3.x,django-models,django-queryset,Python,Django,Python 3.x,Django Models,Django Queryset,我有类型和用户模型。每个类型都有一个id和一个名称,并且存在多对多关系,因此每个用户喜欢0个或多个类型 是否有一个有效的查询来获取所有用户对每种体裁的喜爱程度,并按后代顺序排列? 我目前的方法可行,但效率极低,因为它必须阅读所有用户对每种类型的喜好: In [1]: genres = list(Genre.objects.values('name', 'id')) In[2]: genres Out[2]: [{'id': 10, 'name': 'Rock'}, {'id': 11, '
类型
和用户
模型。每个类型
都有一个id
和一个名称
,并且存在多对多关系,因此每个用户
喜欢0个或多个类型
是否有一个有效的查询来获取所有用户对每种体裁的喜爱程度,并按后代顺序排列?
我目前的方法可行,但效率极低,因为它必须阅读所有用户对每种类型的喜好:
In [1]: genres = list(Genre.objects.values('name', 'id'))
In[2]: genres
Out[2]:
[{'id': 10, 'name': 'Rock'},
{'id': 11, 'name': 'Pop'},
{'id': 12, 'name': 'Hip hop'},
{'id': 13, 'name': 'Electronic'},
{'id': 14, 'name': 'Classical'}]
In [3]: likes_by_users = []
In [4]: users = list(User.objects.all())
In [5]: for u in users:
...: current_user_likes = []
...: likes_by_users.append(current_user_likes)
...: for lg in u.liked_genres.all():
...: current_user_likes.append(lg.pk)
In [6]: likes_by_users
Out[6]:
[[14],
[11, 12],
[11, 10, 13, 12],
[],
[13, 12, 10, 1
[10, 11]]
In [7]: counts = {}
In [8]: for g in genres:
...: counts[g['id']] = {
...: 'name' : g['name'],
...: 'likes': 0
...: }
...: for l in likes_by_users:
...: for gid in l:
...: if gid == g['id']:
...: counts[gid]['likes'] += 1
In [9]: ranking = sorted(list(counts.values()), key=lambda x : x['likes'], reverse=True)
这正是我需要的输出:
In [9]: ranking
Out[9]:
[{'likes': 4, 'name': 'Pop'},
{'likes': 3, 'name': 'Rock'},
{'likes': 3, 'name': 'Hip hop'},
{'likes': 2, 'name': 'Electronic'},
{'likes': 1, 'name': 'Classical'}]
是否有查询或其他方法可以有效地获得所需的排名?试试这个
from django.db.models import Count
Genre.objects.annotate(likes=Count('user')).order_by('-likes')
Django中的许多字段都有实际模型(以及表)支持 您可以通过
获取支持模型。通过:
GenreLikes = User.liked_genres.through
对于简单的多对多关系,该模型将有两个字段/列,user
和genre
,在您的情况下,每个类用户对一个实例/行
因此,你应该能够得到你的排名与公正
GenreLikes.objects.values('genre').annotate(likes=Count('user')).order_by('-likes')
这是文档中的一个示例:Entry.objects.filter(pub\u date\u year=2005)。order\u by('-pub\u date',headline')
annotate
可以直接在querystmanager
上调用,而无需将其链接到all
谢谢您的回答。由于这是一种多对多关系,因此没有user
属性,而是属性。调用Genre.objects.all().annotate(likes=Count('liked_by'))
时,它只列出所有类型。调用Genre.objects.all().annotate(likes=Count('liked_by')).order_by('-likes')
时,它会返回一个包含大量重复条目的庞大流派列表,因此我认为每个条目都代表了用户对某个流派的喜好。有没有办法修复此查询,使结果类似于我的问题中的排名
列表?@SusyP你能将你的用户
(如果不是默认值)和类型
模型添加到问题中吗?@SusyP在我的测试应用程序上,我的决定很好,没有重复条目,不确定你的情况下出了什么问题。谢谢。这种方法很有效,但我必须添加'user'
作为Count()
的参数。如果您能纠正这一点,我将不胜感激。@SusyP完成交易。:)