2009-08-23 59 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