如何在Django中从一组对象中获取平均值?
我有一个简单的评分系统,用来给房产打分。你可以给它打0到5颗星的分数。模型是这样定义的:
def Property(models.Model)
# stuff here
def Rating(models.Model)
property = models.ForeignKey(Property)
stars = models.IntegerField()
我想做的是获取一个房产,找到所有的评分对象,把它们收集起来,然后计算出它们的平均星级。
有没有什么好的方法可以做到这一点?
2 个回答
0
你可以使用 aggregate() 和 annotate() 方法,结合 Avg() 来计算 Rating
模型中星级的平均值,具体的做法如下。*我需要在使用 annotate()
时加上 order_by('pk')
,否则输出的值会是降序排列:
from django.db.models import Avg
# Average the stars in "Rating" model
print(Rating.objects.aggregate(Avg('stars')))
print()
# Average the stars in "Rating" model property by property
for obj in Property.objects.all():
print(
Rating.objects.filter(property=obj)
.aggregate(Avg('stars'))
)
print()
# Average the stars in "Rating" model property by property
for obj in Property.objects.all():
print(obj.rating_set.aggregate(Avg('stars')))
print()
# Average the stars in "Rating" model property by property
qs = Property.objects.annotate(Avg('rating__stars')).order_by('pk')
for obj in qs:
print(obj.rating__stars__avg)
然后,控制台会输出以下内容:
{'stars__avg': 3.7}
{'stars__avg': 3.2}
{'stars__avg': 3.6}
{'stars__avg': 4.0}
{'stars__avg': 3.2}
{'stars__avg': 3.6}
{'stars__avg': 4.0}
3.2
3.6
4.0
另外,你可以把默认的键 stars__avg
改成 starsAvg
,这样可以更清楚地表示星级列的平均值,具体做法如下:
from django.db.models import Avg
# Average the stars in "Rating" model
print(Rating.objects.aggregate(starsAvg=Avg('stars')))
# ↑ Here
print()
# Average the stars in "Rating" model property by property
for obj in Property.objects.all():
print(
Rating.objects.filter(property=obj)
.aggregate(starsAvg=Avg('stars'))
) # ↑ Here
print()
# Average the stars in "Rating" model property by property
for obj in Property.objects.all():
print(obj.rating_set.aggregate(starsAvg=Avg('stars')))
# ↑ Here
print()
# Average the stars in "Rating" model property by property
qs = Property.objects.annotate(starsAvg=Avg('rating__stars')).order_by('pk')
for obj in qs: # ↑ Here
print(obj.starsAvg)
# ↑ Here
这样,默认的键就会变成如下所示:
{'starsAvg': 3.7}
{'starsAvg': 3.2}
{'starsAvg': 3.6}
{'starsAvg': 4.0}
{'starsAvg': 3.2}
{'starsAvg': 3.6}
{'starsAvg': 4.0}
3.2
3.6
4.0
42
你应该使用聚合(文档):
from django.db.models import Avg
p = Property.objects.get(...)
stars_average = p.rating_set.aggregate(Avg('stars')).values()[0]
不过我对我的例子有点不太确定。