Подтвердить что ты не робот

Логическое или 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]>, <Contact: [email protected]>, <Contact: [email protected]>, <Contact: [email protected]>, '...(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 )
4b9b3361

Ответ 1

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