2010-06-04 1 views
14

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

+0

Можем ли мы получить некоторые примеры того, как можно создавать начальные два QuerySets и как они используются? С дополнительной информацией вы можете просто оптимизировать исходный QuerySet вместо того, чтобы добавлять/вычитать? –

+0

qs1 = MyObj1.objects.filter (some_field__gte = value) - qs2, с другой стороны, на самом деле является отношением M2M между определенным экземпляром MyObj2 и экземплярами MyObj1. Я решил, что спрошу о QuerySets, так как я думаю, что ответ будет применимо также к myobj2_instance.myobj1. – Jonathan

ответ

1

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

3

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

Синтаксис может быть что-то вроде этого:

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

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

+0

+1 для того, чтобы сделать это красиво с помощью запросов, но я думаю, что он даже ударил db один раз больше, чем добавление списков! Я предполагаю, какой метод вы предпочитаете, зависит от того, хотите ли вы получить неоплаченные qs или меньшие хиты db! –

+0

Учитывая фактические параметры двух исходных 'QuerySet', вы должны быть в состоянии включить эти параметры в объекты' Q' и перейти к одному удару db – Zach

12

Возвращаясь к django's documentation, вы можете:

new_query_set = query_set_1 | query_set_2 

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

new_query_set = query_set_1 & query_set_2 

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

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

+2

, все еще ищем calssy способ выставить запрос query – philgo20

+0

Использование .exclude() ? – mccc

12

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

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

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

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

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

+0

Это работает только при построении QuerySets, вопрос о ** существующих ** QuerySets. Как можно делать qs1-qs2, когда они уже существуют в качестве запросов. – Curtwagner1984

+0

Изменение существующего набора запросов - это понятие, которое не имеет особого смысла в django. Сделайте это: 'q = Blog.objects.filter (pk__in = q1) .exclude (pk__in = q2)' – DylanYoung

4

Поскольку Джанго 1.11 QuerySets имеют union(), intersection() and difference() methods.

Это также возможно используйте | and & operators с QuerySets (я не мог найти ссылку на это в th e docs, поэтому я думаю, что 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() objects, которые, как QuerySets реализовать | и &, и дополнительно инверсию оператор ~