2009-08-23 66 views
12

这可能是侮辱性的简单并值得纳尔逊蒙兹笑,但我有一个真正的braindead时刻试图通过各种模型关系进行多对多连接。在Django中多对多查找

我有以下型号(简化为您的享受!):

class Document(models.Model): 
    title = models.CharField(max_length=200) 
    author = models.ForeignKey(User, blank=True) 
    content = models.TextField(blank=True) 
    private = models.BooleanField(default=False) 

class UserProfile(models.Model): 
    user = models.ForeignKey(User, unique=True) 
    friends = models.ManyToManyField(User, symmetrical=False, 
            related_name='user_friends') 
    ignored = models.ManyToManyField(User, symmetrical=False, 
            related_name='user_ignored') 

Imaginging以下用户:

  • Alice有3个文件,其中1个是 私人(意思是只有朋友它可以看到 )。她是鲍勃的朋友,是 忽略马洛里和对Eve的精神 (意思是没有存储 的关系)。
  • 马洛里有2个文件,都公开 和对每个人都冷漠。
  • 鲍勃有1个文件是公开的 也是对 大家冷漠。
  • 夏娃被忽略爱丽丝,是 漠不关心马洛里和鲍勃

用户搜索文档应该产生以下:

  • 鲍勃搜索文档应该 看到6,爱丽丝已经让他朋友 ,他可以查看她的私人文件 。
  • 爱丽丝寻找文件应 看到4,鲍勃斯1和她的3.她不 看到马洛里的公开文件为 爱丽丝无视马洛里。
  • 马洛里搜索文档看到 5 - 爱丽丝的公共的,她自己的2 和鲍勃1.爱丽丝无视她没有 轴承什么马洛里能看到的,只是 爱丽丝没有看到马洛里的 文档。
  • 夏娃搜寻文件见3 - Mallory和Bob的公开文件为 她已经忽略了Alice。

基本上,我有一个心理斗争搞清楚过滤器返回我上面描述的查询集。任何人有任何想法?

编辑

由于Ferdinands回答下面我能够通过对螺母什么我开始想,他给了我。 首先,我们希望得到的谁也friended我的人的名单是经过许多反向查找一对多的关系:

friendly_authors = self.user.user_friends.all() 

获取所有我已忽略的人员:

my_ignored = UserProfile.objects.get(user=self.user).ignored.all() 

获取文档,我可以查看列表 - 文档这是可见的,我的,或者谁已经friended我,但我所没有忽视人写的:

docs = Document.objects.filter(
    (Q(viewable=True) | Q(author=self.user) | Q(author__in=friendly_authors)) 
    & ~Q(author__in=my_ignored) 
) 
+0

+1 :) – 2011-03-23 06:13:47

回答

8

这是一个有点棘手,也许你正在寻找类似的东西:

>>> from django.db.models import Q 
>>> me = User.objects.get(pk=1) 
>>> my_friends = UserProfile.objects.get(user=me).friends.all() 
>>> docs = Document.objects.filter(
...  Q(author=me) | (
...   Q(author__in=my_friends) 
...   & ~Q(author__userprofile__ignored=me) 
... ) 
...) 

这将生成以下SQL(我做了原始输出一些格式化):清晰的问题描述

SELECT "myapp_document".* 
FROM "myapp_document" WHERE (
    "myapp_document"."author_id" = %s 
    OR (
     "myapp_document"."author_id" IN (
      SELECT U0."id" FROM "myapp_user" U0 
      INNER JOIN "myapp_userprofile_friends" U1 
       ON (U0."id" = U1."user_id") 
      WHERE U1."userprofile_id" = %s 
     ) 
     AND NOT (
      "myapp_document"."author_id" IN (
       SELECT U2."user_id" FROM "myapp_userprofile" U2 
       INNER JOIN "myapp_userprofile_ignored" U3 
        ON (U2."id" = U3."userprofile_id") 
       WHERE U3."user_id" = %s 
      ) 
      AND "myapp_document"."author_id" IS NOT NULL 
     ) 
    ) 
) 
+0

感谢,你给了我完全我需要的东西来坚持我想要返回的东西 – Steerpike 2009-08-23 15:39:56