[英]How to group by in ManyToMany relationships in Django?
I am creating a web application with Django and I have some problems using its ORM to make queries.我正在使用 Django 创建一个 web 应用程序,我在使用它的 ORM 进行查询时遇到了一些问题。 I have these models:
我有这些模型:
class Country(models.Model):
name = models.CharField(max_length=25)
class Song(models.Model):
title = models.CharField(max_length = 25)
country = models.ForeignKey(Country, on_delete=models.CASCADE, related_name="songs")
ratings = models.ManyToManyField(Country, through='Rating')
class Rating(models.Model):
rating = models.PositiveSmallIntegerField()
country_id = models.ForeignKey(Country, on_delete=models.SET_NULL, null=True)
song_id = models.ForeignKey(Song, on_delete=models.SET_NULL, null=True)
A Country rates many Songs (with ratings 1-10), and a Song can be rated by many Countries, so there's a ManyToMany relationship between these models through the Rating table.一个国家对许多歌曲进行评级(评级为 1-10),而一首歌曲可以被许多国家评级,因此这些模型之间通过评级表存在多对多关系。 I am making a query to get the number of 10 points a Song has received, but I don't know how.
我正在查询一首歌曲获得的 10 分,但我不知道如何。 To do that, I tried this query:
为此,我尝试了以下查询:
result = Rating.objects.filter(rating=10).values('song_id').annotate(ten_points = Count('rating'))
I read Django documentation and I understood that values() method is like group by clause in SQL, but it doesn't work because this query returns a queryset of dictionaries like this:我阅读了 Django 文档,我了解到 values() 方法类似于 SQL 中的 group by 子句,但它不起作用,因为此查询返回这样的字典查询集:
<QuerySet [{'song_id': 1, 'ten_points': 1}, {'song_id': 2, 'ten_points': 1}, {'song_id': 2, 'ten_points': 1}, {'song_id': 3, 'ten_points': 1}, {'song_id': 3, 'ten_points': 1}
Why am I getting different dictionaries with the same key and value 1, instead of a dictionary with the key and the value the total number of ten points?为什么我得到具有相同键和值 1 的不同字典,而不是键和值是十点总数的字典?
You need to use .order_by(…)
to force grouping, so:您需要使用
.order_by(…)
强制分组,所以:
result = Rating.objects.filter(rating=10).values(
'song_id'
).annotate(ten_points=Count('rating')).order_by('song_id')
But in this specific case, it might make more sense to annotate the Song
s:但在这种特定情况下,注释
Song
s 可能更有意义:
Song.objects.filter(
rating__rating=10
).annotate(
ten_points=Count('rating')
)
This will only include Song
s that have at least one Rating
record with rating=10
.这将仅包括具有至少一个Rating
rating=10
的Rating
记录的Song
。 If you want to annotate all Song
s, you can use:如果要对所有
Song
进行注解,可以使用:
from django.db.models import Q
Song.objects.annotate(
ten_points=Count('rating', filter=Q(rating__rating=10))
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.