Добрый день.
Стояла задача - разбить множество всех записей в одной таблице БД на непересекающиеся подмножества, в сумме дающие полное мноджество, в соответствии с несколькими условиями. Иначе говоря - факторизовать. Я всегда считал что если написать:
set1 = Models.objects.filter(condition A)
set2 = Models.objects.exclude(condition A)
То это и будет факторизацией всего множества Models на два класса. Т.е. set1 не пересекается с set2, в их объединение дает все множество Models. Но оказалось что это не так.
Решил поделится своим наблюдением, может это кому-то пригодится. А может кто-то знает причину и сможет ее объяснить.
Теперь конкретнее. Есть модель Contragents, есть ссылающиеся на нее модели Contact и Staff.
Я создаю запросы:
con1 = Contragents.objects.filter(~Q(contact__ctype='E', contact__staff=None, contact__actual=True)|~Q(contact__ctype__in=['M','P'], contact__staff=None, contact__actual=True)|~Q(staff__main=True)|Q(contact__actual=False)).distinct()
con2 = Contragents.objects.exclude(~Q(contact__ctype='E', contact__staff=None, contact__actual=True)|~Q(contact__ctype__in=['M','P'], contact__staff=None, contact__actual=True)|~Q(staff__main=True)|Q(contact__actual=False)).distinct()
И у меня получается что одна запись у которой contact__actual = False попадает не только в con1 но и в con2.
Решить эту проблему можно довольно легко, изменив запрос:
con2 = Contragents.objects.exclude(~Q(contact__ctype='E', contact__staff=None, contact__actual=True)|~Q(contact__ctype__in=['M','P'], contact__staff=None, contact__actual=True)|~Q(staff__main=True)).exclude(contact__actual=False).distinct()
Но почему не работает первый вариант, я так и не понял.