[Answered ]-Django orm – annotate / aggregation (avg) in subquery

1👍

You can filter with:

Movie.objects.annotate(avg_rating=Avg('users__rating'))

the reason we use users is because that is the value for the related_name='users', but does not make much sense.

You can rename it to:

from django.conf import settings

from django import models


class Review(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    movie = models.ForeignKey(
        'Movie', on_delete=models.CASCADE, related_name='reviews'
    )
    rating = models.PositiveIntegerField(
        validators=[MinValueValidator(1), MaxValueValidator(10)],
        null=True,
        blank=True,
    )
    advice = models.CharField(max_length=500, null=True, blank=True)
    objects = UserMovieRelManager()

and thus query with:

Movie.objects.annotate(avg_rating=Avg('reviews__rating'))

Note: Models normally have no Rel suffix. A model is not a relation or table, it is stored in a relational database as a table, but even then it has extra logic like validators, managers, etc.


Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.

Leave a comment