Django:根据相交对象的数量订购商品(共同的朋友)

时间:2011-07-19 23:35:27

标签: sql django django-models

我正在使用Django编写社交网络应用程序,并且需要实现类似于Facebook“共同朋友”概念的功能。我有一个这样的简单模型:

class Friend(models.Model):
    user = models.ForeignKey(User)
    guid = models.BigIntegerField()
    name = models.TextField()

    class Meta:
        unique_together = ['user', 'facebook_id']

它代表了我网站的用户和他的一个朋友之间的关系。 (朋友不一定也是用户)两个用户之间的共同朋友的数量可以计算为他们的朋友列表的交集,换句话说,

users = User.objects.all()
friends = Friend.objects.filter(user=request.user)
friend_ids = [f.guid for f in friends]
for user in users:
    user.mutual = Friend.objects.filter(user=user, guid__in=friend_ids).count()

(更有效的方法是获得上述奖励积分)。

我的主要问题是,计算了用户之间的共同朋友数量后,我现在如何根据当前用户的共同朋友数量订购users查询集?我在这种情况下,不能将计数保存为注释或额外字段,因为它依赖于正在检查的特定用户,并且仅依赖于他的总朋友的某个子集。我能以某种巧妙的方式使用annotateextra方法吗?或者是raw sql查询唯一的出路?如果是这样,怎么样?

总结

计算每个用户的共同朋友数量不是问题。鉴于每个用户的信息,您如何根据该号码继续订购QuerySet

1 个答案:

答案 0 :(得分:2)

不确定这是否正是您所寻找的......但

# get current users friends (assuming guid is unique for a friend?)
user_friend_guids = Friend.objects.values_list('guid', flat=True).filter(user=user)

# get Friend objects where user not current user, is in user_friend_list, group and count by user
mutual_friends = Friend.objects.values('user__username') \
                               .filter(guid__in=user_friend_guids).exclude(user=user) \
                               .annotate(number_mutual_friends=Count('user')) \
                               .order_by('-number_mutual_friends')

这将返回一个用户名列表,其中包含与用户共享的朋友数量,按照他们共享的数量排序。

然后在模板中:

{% for mutual_friend in mutual_friends %}
    {{mutual_friend.user__username}} - {{mutual_friends.number_mutual_friends}}
{% endfor %}