2012-10-12 30 views
6

我是Python和Django的新手,所以请耐心等待我。与Django的复杂查询(所有朋友的帖子)

我有以下型号:

class User(models.Model): 
    name = models.CharField(max_length = 50) 
    ... 

class Post(models.Model): 
    userBy = models.ForeignKey(User, related_name='post_user') 
    userWall = models.ForeignKey(User, related_name='receive_user') 
    timestamp = models.DateTimeField() 
    post = models.TextField() 

class Friend(models.Model): 
    user1 = models.ForeignKey(User, related_name='request_user') 
    user2 = models.ForeignKey(User, related_name='accept_user') 
    isApproved = models.BooleanField() 
    class Meta: 
     unique_together = (('user1', 'user2'),) 

我知道这可能不是使用Django来处理它的最佳/最简单的方法,但我学会了这种方法,我想保持这个样子。

现在,我想要做的是获取所有帖子从一个人,它的朋友。现在的问题是如何用Django过滤器做到这一点?

我想在SQL它会是这个样子:

SELECT p.* FORM Post p, Friend f 
WHERE p.userBy=THEUSER OR (
    (f.user1=THEUSER AND f.user2=p.userBy) OR 
    (f.user2=THEUSER AND f.user1=p.userBy) 
) 

不保证正确性,只是为了给我找的结果的想法。

回答

8
from django.db.models import Q 

Post.objects.filter(\ 
    Q(userBy=some_user) | \ 
    Q(userBy__accept_user__user1=some_user) | \ 
    Q(userBy__request_user__user2=some_user)).distinct() 

UPDATE

对不起,那是我的错。我没有注意你的related_name值。查看上面更新的代码。单独使用userBy__accept_useruserBy__request_user将无法​​正常工作,因为那将是对Friend的参考,您无法将其与User进行比较。我们在这里做的是跟随与Friend的反向关系,然后一旦我们在那里,看到其他朋友请求中的用户是否是有问题的用户。

这也说明了适当描述反向关系的重要性。很多人犯了同样的错误,并在创建FK的模型(User)后命名为related_name,实际上,当我们谈论逆转FK时,我们现在谈论的是Friend。简单地说,您的相关名称会更有意义,如:friend_requestsaccepted_friends

+0

是否有来自用户的外键,必须指向朋友? – cesar09

+0

不会。“__friend”位跟随关系向后,因为'Friend'对'User'有FK。 –

+0

有关更多信息,请参阅[跨越关系的查找]的文档(https://docs.djangoproject.com/en/dev/topics/db/queries/#lookups-that-span-relationships)。 –

0
(with User u) 
friends_u1 = Friend.objects.filter(user1 = u).getlist('user2_id', flat=True) 
friends_u2 = Friend.objects.filter(user2 = u).getlist('user1_id', flat=True) 
friends_and_user = friends_u1+friends_u2+u.id 

Post.objects.filter(userBy__id__in = friends_and_user) 
+0

标准方法是使用'Q'对象。你能否澄清一下_为什么你选择了不同的方法? – Tadeck

+0

你在哪里得到“标准的方法是使用Q对象”?它没有在文档中说过。另外,对于一个django新手来说,这个突破的方法可能更容易理解。 – Colleen

+4

来自体验。您首先收集所有ID,然后您将其用于查询。考虑一下你会有500个朋友的情况,这个问题可能会很大。是的,Django新手可以使用这个解决方案(或者有人知道_why_和_when_可能会更好),但这不是关于什么更容易理解,而是什么是最好的(或者至少是“好的”)。当涉及到“标准方法”部分时:[请阅读Django中复杂查询的文档](https://docs.djangoproject.com/en/dev/topics/db/queries/#complex-lookups-with-q-对象)。 – Tadeck