Простой способ объединения и вычитания QuerySet в django?

Рассмотрим два объекта QuerySet того же класса. Есть ли простой способ объединить их в один QuerySet, вычислив объединение? Кроме того, есть ли простой способ их вычесть? Удаление всех элементов, которые появляются в обоих наборах из одного из наборов?

Ответы

Ответ 1

Возвращаясь к документации django, вы можете:

new_query_set = query_set_1 | query_set_2

Это работает как логическое ИЛИ, которое фактически является дополнением без дубликатов. Это отвечает на дополнительный аспект, и AFAIK вообще не попадает в db!

new_query_set = query_set_1 & query_set_2

Это работает как логическое И.

По-прежнему отсутствует способ вычитать QuerySets. Мне трудно поверить, что сообщество не обходилось элегантно...

Ответ 2

Вычтите QuerySet из другого QuerySet, используя ту же модель.

Это работает - но, вероятно, медленно

queryset_with_hello = Blog.objects.filter(name__icontains='hello')
queryset_without_hello = Blog.objects.exclude(pk__in=queryset_with_hello)

Прочитайте соображения производительности в документации django:

https://docs.djangoproject.com/en/dev/ref/models/querysets/#in

Ответ 3

Вы можете использовать объект Q.

Синтаксис может быть примерно таким:

added_query_set = YourModel.objects.\
         filter(Q(id__in=old_query_set_1)|Q(id__in=old_query_set_2))

Вероятно, вы можете оптимизировать свои фактические потребности и получить количество удалений db (сейчас это 3), но это должно заставить вас начать.

Ответ 4

Поскольку Django 1.11, QuerySets имеют union(), intersection() и difference() методы.

Также можно использовать | и & operator с QuerySets (я не смог найти ссылку на это в документах, поэтому я думаю, union() и intersection() - это предпочтительный способ объединить два запроса.

qs3 = qs1.union(qs2)         # or qs3 = qs1 | qs2
qs3 = qs1.intersection(qs2)  # or qs3 = qs1 & qs2
qs3 = qs1.difference(qs2)    # the ^ operator is not implemented.

Вы также можете использовать Q() объекты, которые, как QuerySets, реализуют | и &, а также оператор инверсии ~

Ответ 5

Я думаю, что для операций, как это, нужно их просчитать. Поэтому вы можете вызвать list() на них и работать с ними с помощью общих операций с списком python!