Django 从外键对象字段的值列表中获取平均值

Django 从外键对象字段的值列表中获取平均值,django,Django,我正在制作一个电影分级应用程序。每部电影都可以由用户分级 class MovieRating(models.Model): movie = models.OneToOneField(Movie) users = models.ManyToManyField(User, through='UserRating') average_rating = ??? or whichever is better @property def average_r

我正在制作一个电影分级应用程序。每部电影都可以由用户分级

class MovieRating(models.Model):
    movie = models.OneToOneField(Movie)
    users = models.ManyToManyField(User, through='UserRating')
    average_rating = ???

    or whichever is better

    @property
    def average_rating(self):
        ???

class UserRating(models.Model):
    movie_rating = models.ForeignKey(MovieRating)
    user = models.ForeignKey(User)
    rating = models.PositiveIntegerField(
        default=1,
        validators=[
            MinValueValidator(1),
            MaxValueValidator(10)
        ]
    )
    review = models.TextField()
    pub_date = models.DateTimeField(default=timezone.now)

    class Meta:
        unique_together = ('movie', 'user')
我想得到那部电影的平均收视率。意义

average_rating=(用户对电影的总评分)/(电影的总用户)

我可以通过

movie\u rating.users.count()

但是我如何获得每个用户的总评分呢?或者我能做些什么来获得一部电影的平均收视率

更新:

现在我正在这样做,但我不知道这是否是正确的方式:

def average_rating(self):
    if self.users.count() == 0:
        return 0.0
    rates = 0
    rating_list = [user_rating.rating for user_rating in self.userrating_set.all()]
    for r in rating_list:
        rates = r + rates
    return rates / self.users.count()
尝试以下方法:

sum([rate.rating for rate in movie_rating.userrating_set.all()])
尝试以下方法:

sum([rate.rating for rate in movie_rating.userrating_set.all()])
,包括平均值。在您的情况下,您可以通过对象与其属性的反向关系在相关字段上进行聚合。由于聚合是由数据库本机执行的,因此通常建议不要手动计算聚合值

所以在你的平均评级法中

from django.db.models import Avg

...

@property
def average_rating(self):
    return self.userrating_set.aggregate(Avg('rating'))['rating__avg']
,包括平均值。在您的情况下,您可以通过对象与其属性的反向关系在相关字段上进行聚合。由于聚合是由数据库本机执行的,因此通常建议不要手动计算聚合值

所以在你的平均评级法中

from django.db.models import Avg

...

@property
def average_rating(self):
    return self.userrating_set.aggregate(Avg('rating'))['rating__avg']

是的,我也是这样做的。即使列表中有许多对象,也可以循环吗?要么如此,要么在添加新的评级后重新计算评级。这意味着要么在保存时重新计算,要么为此创建一个后期保存。是的,我也是这样做的。即使列表中有许多对象,也可以循环吗?要么如此,要么在添加新的评级后重新计算评级。这意味着要么在保存时重新计算,要么为此创建后期保存。如何使用round()进行此操作?由于
(1+5+2)/3=8/3=2.6666…67
,我想将小数点四舍五入到1位,例如2.7。但是
round(self.userrating\u set.aggregate(Avg('rating'))['rating\u Avg'],1)
给了我一个类型错误,需要一个浮点数。当我在聚合平均数上尝试时,舍入有效,它是否正确返回2.666。。。你期待什么?这一行应该可以正常工作,因此它可能与周围的代码有关。您可以使用
quantize()
实现四舍五入到小数点后1位。用法示例:
self.userrating\u set.aggregate(Avg('rating')).get('rating\u Avg').quantize(Decimal('1.0'))
这也需要
from Decimal import Decimal
。我已经知道如何找到Avg()值,但是如何将这个Avg值定义到另一个模型中,以便在端点中使用?如何使用round()?由于
(1+5+2)/3=8/3=2.6666…67
,我想将小数点四舍五入到1位,例如2.7。但是
round(self.userrating\u set.aggregate(Avg('rating'))['rating\u Avg'],1)
给了我一个类型错误,需要一个浮点数。当我在聚合平均数上尝试时,舍入有效,它是否正确返回2.666。。。你期待什么?这一行应该可以正常工作,因此它可能与周围的代码有关。您可以使用
quantize()
实现四舍五入到小数点后1位。用法示例:
self.userrating\u set.aggregate(Avg('rating')).get('rating\u Avg').quantize(Decimal('1.0'))
这也需要
from Decimal import Decimal
。我已经知道如何找到Avg()值,但如何将该Avg值定义到另一个模型中,以便在端点中使用?