2011-10-12 76 views
11

我有很多型號,以一對多的關係是這樣的:邏輯或Django的很多很多的查詢返回重複的結果

class Contact(models.Model): 
    name = models.TextField() 
    address = models.TextField() 

class Mail(models.Model): 
    to = models.ManyToManyField(Contact, related_name='received_mails') 
    cc = models.ManyToManyField(Contact, related_name='cced_mails') 

我想獲得的一組被用在接觸到字段或CC字段爲給定的電子郵件。讓我們試試:

>>> Contact.objects.filter(received_mails__id=111) 
[<Contact: [email protected]>] 
>>> Contact.objects.filter(cced_mails__id=111) 
[<Contact: [email protected]>] 

到目前爲止好。我們每個關係都有一個聯繫人。但將它們都放入同一個QuerySet中將會很好。

>>> Contact.objects.filter(Q(received_mails__id=111) | Q(cced_mails__id=111)) 
[<Contact: [email protected]>, <Contact: [email protected]>, <Contact: [email protected]>, <Contact: [email protected]>, <Contact: [email protected]>, <Contact: [email protected]>, <Contact: [email protected]>, <Contact: [email protected]>, <Contact: [email protected]>, <Contact: [email protected]>, <Contact: [email protected]>, <Contact: [email protected]>, <Contact: [email protected]>, <Contact: [email protected]>, <Contact: [email protected]>, <Contact: [email protected]>, <Contact: [email protected]bar.com>, <Contact: [email protected]>, <Contact: [email protected]>, <Contact: [email protected]>, '...(remaining elements truncated)...'] 

發生了什麼事?我有一種感覺,這與在SQL中連接表有關,但我並不真正瞭解發生在多對多關係下的情況。這可能是因爲我想做的事很愚蠢,或者有一個簡單的方法來做到這一點。無論哪種方式,我很高興能夠設置在正確的道路上。

編輯:這是查詢集的查詢:

SELECT `mailshareapp_contact`.`id`, `mailshareapp_contact`.`name`, 
`mailshareapp_contact`.`address` FROM `mailshareapp_contact` 
LEFT OUTER JOIN `mailshareapp_mail_to` 
ON (`mailshareapp_contact`.`id` = `mailshareapp_mail_to`.`contact_id`) 
LEFT OUTER JOIN `mailshareapp_mail_cc` 
ON (`mailshareapp_contact`.`id` = `mailshareapp_mail_cc`.`contact_id`) 
WHERE (`mailshareapp_mail_to`.`mail_id` = 111 
OR `mailshareapp_mail_cc`.`mail_id` = 111) 

回答

16

由於SQL返回所有匹配的記錄,Django的盡職盡責地將它們映射到對象。你正在尋找的是使SQL將所有重複行合併爲一個的queryset方法。

+0

這樣做,謝謝。 (對不起,我現在還不能投票)。這通過使用SELECT DISTINCT而不是SELECT來更改查詢。我不明白如果沒有它,你會如何得到許多重複的東西,但是我的直接問題已經解決了。 –

+0

對於滿足至少一個JOIN和一個WHERE子句的'mailshareapp_contact'×('mailshareapp_mail'到'+'NULL')×('mailshareapp_mail_cc' +'NULL')的每個組合,您將得到一個單獨的行。順便說一句,如果上述回答你的問題,你可以隨時將其標記爲公認的迴應。 – patrys