Django实现好友列表中各用户平均评分查询方法
如何编写查询返回好友列表中每个用户的平均评分
模型定义(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}]
正确实现方式
使用Django ORM的分组+聚合功能即可实现,需要先导入Avg聚合函数:
from django.db.models import Avg # 传入当前用户对应的FriendList实例friends avg_rating_result = Checkin.objects.filter( beer=1, user__in=friends.friend.all(), # 可选:过滤掉未评分的记录,避免空值干扰计算 rating__isnull=False ).values("user").annotate( avg_rating=Avg("rating") )
逻辑说明
values("user"):指定按关联的用户ID字段对查询结果分组annotate(avg_rating=Avg("rating")):对每个用户分组下的所有rating字段计算平均值,生成名为avg_rating的聚合字段- 最终返回的QuerySet迭代后,结构和预期完全一致,可直接使用。
内容的提问来源于stack exchange,提问作者Haavardnk
相关产品推荐
相关产品推荐

