Логический или Django много-много запросов возвращает дубликаты результатов - PullRequest
12 голосов
/ 12 октября 2011

У меня есть модели со многими отношениями, например:

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')

Я хочу получить набор контактов, которые находятся либо в поле to, либо в поле cc для данного электронного письма.Давайте попробуем:

>>> Contact.objects.filter(received_mails__id=111)
[<Contact: fred@foo.com>]
>>> Contact.objects.filter(cced_mails__id=111)
[<Contact: joe@bar.com>]

Пока все хорошо.У нас есть один контакт для каждого отношения.Но было бы неплохо поместить их обоих в один и тот же QuerySet.

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

Что случилось?У меня есть ощущение, что это связано с объединением таблиц в SQL, но я не совсем понимаю, что происходит в тайнике со многими отношениями.Возможно, то, что я пытаюсь сделать, глупо, или есть простой способ сделать это.В любом случае, я рад быть выбранным по правильному пути.

Редактировать: это запрос QuerySet:

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 )

1 Ответ

17 голосов
/ 12 октября 2011

Поскольку SQL возвращает все совпадающие записи, Django покорно сопоставляет их с объектами.Что вам нужно, так это метод набора запросов .distinct(), который позволяет SQL свернуть все дублирующиеся строки в одну.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...