我有一个友谊模型,其中有两个与之关联的相关用户对象。我想写一个方法,它接受用户并返回该用户的朋友的列表。我这样做是通过:
friends = Friendship.objects.filter(Q(user1=user) | Q(user2=user))
friends_list = [f.user1 if user == f.user2 else f.user2 for f in friends]
但这会导致查询集中返回的每个用户的查询(例如数百个查询)。我可以通过以下方式写出来:
friends = Friendship.objects.select_related().filter(Q(user1=user) | Q(user2=user))
friends_list = [f.user1 if user == f.user2 else f.user2 for f in friends]
但是这会在用户表上执行INNER JOIN。我也可以通过自定义SQL编写它,
friends = User.objects.raw("""
SELECT * FROM usertable WHERE id IN (SELECT
user1_id FROM friendstable WHERE user2_id=%d) OR id IN
(SELECT user2_id FROM lists_friendship WHERE user1_id=%d);
""" % (user.pk, user.pk))
但我认为必须有一种方法可以在ORM内部进行,而无需进行所有额外的查找。我试图用id__in
做一些事情,但我找不到从朋友查询集中获取用户ID的方法。
答案 0 :(得分:0)
假设您设置的友谊模型与下面的示例类似,并使用friend_set
作为模型中from_friend
字段的相关名称,获取用户朋友列表可以简单到一个基本的列表理解:
friends = [friendship.to_friend for friendship in user.friend_set.all()]
这甚至允许您在模板中访问用户的朋友,而不必将其作为变量传递:
{% for friendship in user.friend_set.all %}
{{ friendship.to_friend.username }}
{% endfor %}
您的友谊模型如下所示:
class Friendship(models.Model):
from_friend = models.ForeignKey(
User, related_name='friend_set'
)
to_friend = models.ForeignKey(
User, related_name='to_friend_set'
)
def __unicode__(self):
return u'%s, %s' % (
self.from_friend.username,
self.to_friend.username
)
class Meta:
unique_together = (('to_friend', 'from_friend'), )
这是一篇关于在Django中构建朋友网络的精彩文章: http://www.packtpub.com/article/building-friend-networks-with-django-1.0
请注意,您不必同时检查from_friend
和to_friend
以获取用户好友列表。如果您有以下/关注者友谊模型,您只需要所有友情实例与from_friend = user,如果您有双重选择友谊模型,您可以按照Facebook所做的操作,并为受邀朋友添加一个实例{{{ 1}}一旦他们接受了朋友的邀请。