2010-06-04 63 views
14

Considere dos objetos QuerySet de la misma clase. ¿Existe una manera simple de unificarlos en un único QuerySet calculando la unión? Además, ¿hay una manera simple de restarlos? ¿Eliminando todos los elementos que aparecen en ambos conjuntos de uno de los conjuntos?forma simple para la unión y sustracción de QuerySet en django?

+0

¿Podemos obtener algunos ejemplos de cómo se generan las dos QuerySets inicial y cómo se usan? Con más información, ¿puede simplemente optimizar su QuerySet original en lugar de tener que sumar/restar? –

+0

qs1 = MyObj1.objects.filter (some_field__gte = value) - qs2 por otro lado es en realidad una relación M2M entre una cierta instancia MyObj2 y las instancias MyObj1 Pensé que preguntaré sobre QuerySets, ya que creo que la respuesta sería aplicable a myobj2_instance.myobj1 también. – Jonathan

Respuesta

1

Creo que para operaciones como esta debe evaluarlas. ¡Así que puede llamar al list() y trabajar en ellos con las operaciones comunes de la lista de Python!

3

Puede usar el Q object.

La sintaxis podría ser algo como esto:

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

Es probable que pueda optimización en función de sus necesidades reales y obtener la cantidad de db golpea hacia abajo (en este momento es 3), pero esto debe empezar.

+0

+1 por hacerlo bien con querysets, pero supongo que incluso está llegando al db una vez más que agregar listas. ¡Supongo que el método que prefieres depende de si quieres un qs no evaluado o éxitos de DB menores! –

+0

Teniendo en cuenta los parámetros reales de los dos 'QuerySet's originales, debería poder incluir esos parámetros en los objetos' Q' y bajar a un db presionar – Zach

12

Volviendo a django's documentation, se puede:

new_query_set = query_set_1 | query_set_2 

Esto funciona como un OR lógico que en realidad es además sin duplicados. ¡Esto responde al aspecto de la suma y AFAIK no golpea el DB en absoluto!

new_query_set = query_set_1 & query_set_2 

Esto funciona como un AND lógico.

Aún falta cómo restar QuerySets. Es difícil para mí creer que esto no ha sido tratado con elegancia por la comunidad ...

+2

buscando aún la manera más fácil de suscribir el conjunto de interrogación – philgo20

+0

Usando .exclude() ? – mccc

12

Reste un QuerySet de otro QuerySet utilizando el mismo modelo.

Esto funciona - pero es probable que poco a poco

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

Lea las consideraciones de rendimiento en la documentación de Django:

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

+0

Esto solo funciona al construir QuerySets, la pregunta es acerca de ** ** QuerySets existentes. ¿Cómo se podría hacer qs1- qs2 cuando ya existen como conjuntos de consulta? – Curtwagner1984

+0

La modificación de un conjunto de consulta existente es una noción que no tiene mucho sentido en django. Haga esto: 'q = Blog.objects.filter (pk__in = q1) .exclude (pk__in = q2)' – DylanYoung

4

Desde Django 1.11, QuerySets tienen union(), intersection() and difference() methods.

También es posible use | and & operators con QuerySets (no pude encontrar una referencia a esto en e documentos, así que supongo que union() y intersection() es la forma preferida de combinar dos conjuntos de consulta.

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. 

también puede utilizar Q() objects que al igual que QuerySets implementar | y &, y, además, la inversión del operador ~

Cuestiones relacionadas