2011-12-02 35 views
0

我有以下型號:選擇所有Django的外鍵模式,如果條件或部分,如果其他條件

class Project(models.Model): 
    title = models.CharField(max_length=75) 
    description = models.CharField(max_length=250) 
    project_collaborators = models.ManyToManyField(User) 
... 

class Node(models.Model): 
    title = models.CharField(max_length=75) 
    collaborators = models.ManyToManyField(User) 
    project = models.ForeignKey(Project) 

我想要做的是選擇的所有項目,其中一個用戶是project_collaborator,以及所有與該項目相關聯的節點,並且還選擇用戶是項目內節點上的協作者的所有項目,但是每個項目中只選擇該用戶是協作者的節點。

用戶可能是project_collaborator以及節點上的協作者,但是這應該只返回項目/節點的一個實例。

到目前爲止我所得到的最接近的是Project.objects.filter(Q(node__collaborators=user) | Q(project_collaborators=user)).distinct(),但這並不完全符合我的願望。

編輯:解我用

我開始與這views.py讓用戶將與相關聯的所有項目:

projects = Project.objects.select_related().filter(Q(project_collaborators=request.user) | Q(canvas__collaborators=request.user)).distinct() 

然後在模板中我所做的:

{% for project in projects %} 

    {{ project.title }} 
    <ul> 
    {% for node in project.node_set.all %} 

     {% if request.user in project.project_collaborators.all or request.user in node.collaborators.all %} 

      <li>{{ node.title }}</li> 

     {% endif %} 

    {% endfor %} 
    </ul> 
    <br /> 

{% endfor %} 

這使我可以打印出所有節點,如果用戶是項目協作者,或者只有特定節點,如果他們只是節點協作者,同時仍然打印出所有項目嘿與之相關。

+1

你想項目或節點?因爲如果在第二種情況下,您只希望Node的用戶是合作者!我們將不得不回顧項目的筆記清單!否則,如果我們回顧項目,它會回顧所有的筆記!不僅僅是用戶可以訪問的那些! –

+0

我不認爲你可以在單個ORM調用中完成所有這些工作。我將首先創建選擇所需數據的單個語句,然後查看組合這些語句的方法。 – Brandon

回答

2

我給你兩種方法:

這樣做可以用盡可能少的查詢儘可能

獲取Node對象,然後用它們來獲得Project對象,而不是周圍的其他方法:

nodes = Node.objects.filter(Q(project__project_collaborators=user) | Q(collaborators=user)).select_related('project').distinct() 

現在你只有你想要的節點,只有你想要的節點。你所擁有的是該項目的多重表示。如果你只需要節點,這不是問題。如果你需要的項目清單,你可以使用Python編譯這個很輕鬆了,雖然不是作爲一個QuerySet

projects = [] 
for node in nodes: 
    if node.project not in projects: 
     projects.append(node.project) 

如果您需要項目爲QuerySet,你可以用一個額外的查詢讓他們 - - 這裏是該代碼(代替塊以上):

project_ids = set([node.project.id for node in nodes]) 
projects = Project.objects.filter(id__in=project_ids) 

請注意,你必須與他們適當Node實例重新關聯Project情況下,如果你需要的關聯關係:

projects_and_nodes = {} 
for project in projects: 
    projects_and_nodes[project] = [node for node in nodes if node.project == project] 

在乾淨的代碼儘可能

這樣做,你似乎已經知道如何得到你想要的Project實例 - 你還沒有完全得到權得到正確的Node實例片。你需要一旦你檢索到稱Project一些邏輯:

# pseudocode 
if the user is a collaborator on this project: 
    get all the nodes 
else: 
    get only the nodes applicable to the user 

在這種情況下,使用您所提供的代碼來獲取項目,然後在這裏Python是用於獲取適當的節點:

希望有幫助。 :)

+0

感謝您的幫助。我結束了對你所建議的以及我已經擁有的東西的一些小組合。我會用我所做的來編輯第一篇文章。 – Samsquanch