Reputation: 2748
I am making a movie rating app. Each movie can be rated by users.
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')
I want to get the average rating of for that movie. Meaning
average_rating = (Total rating by user for a MovieRating) / (Total users of MovieRating)
I can get the total users of a MovieRating by
movie_rating.users.count()
But how do I get the rating of every users in Total? Or else what can I do to get the average rating for a movie?
update:
Now I am doing this way, but I don't know whether this is the right way to go:
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()
Upvotes: 0
Views: 1033
Reputation: 696
Django supports aggregation queries, including averaging. In your case you can aggregate on the related field through the object's reverse relation to its intermediary model. Since aggregations are performed natively by the database, they are generally recommended over manually calculating their values.
So in your average rating property method
from django.db.models import Avg
...
@property
def average_rating(self):
return self.userrating_set.aggregate(Avg('rating'))['rating__avg']
Upvotes: 4
Reputation: 490
Try something like:
sum([rate.rating for rate in movie_rating.userrating_set.all()])
Upvotes: 0