#python #django
#python #django
Вопрос:
У календарей есть владелец и есть ManyToMany
поле «помощники» у меня есть календарь, у которого есть 2 помощника, один из которых является его владельцем. Я думаю, что эти 3 строки кода в оболочке django могут достаточно хорошо объяснить странное поведение.
In [17]: Calendar.objects.filter(assistants=customer).exclude(owner=customer)
Out[17]: <QuerySet []>
In [20]: Calendar.objects.filter(owner=customer)
Out[20]: <QuerySet [<Calendar: aliz cal>, <Calendar: yassi has a calendar>]>
In [19]: Calendar.objects.filter(owner=customer) | Calendar.objects.filter(assistants=customer).exclude(owner=customer)
Out[19]: <QuerySet [<Calendar: aliz cal>, <Calendar: aliz cal>, <Calendar: yassi has a calendar>]>
Конечно, ожидалось, что результатом объединения набора запросов будет их фактическое объединение.
Комментарии:
1. интересно, однако,
assistants=customer
что причиной этого стала фильтрация набора запросов.
Ответ №1:
Предполагая, что это для django 1.11 :
|
не представляет собой профсоюз. Он представляет собой комбинацию OR (которая поддерживает все соединения; следовательно, aliz отображается дважды) из двух наборов запросов.
qs1.filter(x=1) | qs2.exclude(x=1)
переводится как:
SELECT STUFF FROM TABLES_AND_JOINS WHERE (x = 1 OR NOT (x = 1))
В то время qs1.filter(x=1).union(qs2.exclude(x=1))
как переводится в:
SELECT STUFF FROM TABLE1 WHERE x = 1 UNION SELECT STUFF FROM TABLE2 WHERE NOT x = 1
Используйте str(qs.query)
, чтобы увидеть SQL.
Ответ №2:
То, что вы делаете OR
, — WHERE
это добавление предложений обоих запросов, что отличается от объединения (и немного сложно при объединении; здесь ORM переключается с внутреннего соединения в наборе запросов # 1 на внешнее соединение в наборе запросов # 3 для учета второго запроса, в котором нет соединений). Смотрите соответствующие документы.
Попробуйте union()
, доступно с Django 1.11 и далее:
qs1 = Calendar.objects.filter(assistants=customer).exclude(owner=customer)
qs2 = Calendar.objects.filter(owner=customer)
qs3 = qs1.union(qs2)