如何在Django中从一组对象中获取平均值?

17

我有一个简单的房产评分系统。你需要给它一个5分制的分数(星级)。这些模型的定义如下:

def Property(models.Model)
    # stuff here

def Rating(models.Model)
    property = models.ForeignKey(Property)
    stars = models.IntegerField()
我想做的是获取一个属性,找到所有的Rating对象,将它们收集起来,然后从中获取平均值'stars'。 有什么好的想法吗?
2个回答

41

你应该使用聚合(doc)

from django.db.models import Avg

p = Property.objects.get(...)
stars_average = p.rating_set.aggregate(Avg('stars')).values()[0]

对于我的示例有点不确定。


示例非常准确 :) 非常感谢drmegahertz。 - dotty
2
对于单个查询中的多个属性,您可以使用 Property.objects.annotate(Avg('rating__stars')) - Zach
如何在 ratings = ArrayField(models.IntegerField(), blank=True,null=True) 上计算平均值? - Piyush S. Wanare

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 列的默认键 stars__avgstarsAvg

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接