Django: Получение среднего рейтинга для каждого пользователя

Как составить запрос, возвращающий список средних оценок пользователей в friendlist?

models.py

class Beer(models.Model):
    id = models.BigIntegerField(primary_key=True)
    name = models.CharField(max_length=150)
    ...

class Checkin(models.Model):
    id = models.IntegerField(primary_key=True)
    rating = models.FloatField(blank=True, null=True)
    user = models.ForeignKey(User, on_delete=CASCADE)
    ...

class FriendList(models.Model):
    user = models.OneToOneField(User, on_delete=CASCADE, primary_key=True)
    friend = models.ManyToManyField(User, related_name="friends")

база данных (postgresql)

user beer rating
1 1 4.2
1 1 3.5
1 1 4.0
2 1 4.1
2 1 3.7

Мой текущий запрос, чтобы получить все регистрации друзей:

Checkin.objects.filter(beer=1, user__in=friends.friend.all())

Что дает мне что-то вроде:

[{user: 1, rating: 4.2}, {user: 1, rating: 3.5},...,{user: 2, rating: 4.1}...]

Что я хочу:

[{user: 1, avg_rating: 4.1}, {user: 2, avg_rating: 3.8}]

Более логично .annotate(…) [Django-doc] объекты User, так:

from django.db.models import Avg

friends.friend.filter(
    checkin__beer_id=1
).annotate(
    rating=Avg('checkin__rating')
)

Where checkin__ is the related_query_name=… [Django-doc] for the user from Checkin to the User model. If you did not specify a related_query_name=…, then it will use the value for the related_name=… [Django-doc], and if that one is not specified either, it will use the name of the source model in lowercase, so checkin.

Объекты User, возникающие из этого набора запросов, будут иметь дополнительный атрибут .rating, содержащий среднее значение rating над Checkins для данного beer_id.


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.

Вернуться на верх