2010-06-04 11 views
14

Considerare due oggetti QuerySet della stessa classe. C'è un modo semplice per unificarli in un singolo QuerySet calcolando l'unione? Inoltre, c'è un modo semplice per sottrarli? Rimuovendo tutti gli elementi che appaiono in entrambi i set da uno dei set?modo semplice per unione e sottrazione di QuerySet in django?

+0

Possiamo ottenere alcuni esempi di come si generano i primi due querysets e come vengono utilizzati? Con più informazioni potresti essere in grado di ottimizzare semplicemente il tuo QuerySet originale invece di dover aggiungere/sottrarre? –

+0

qs1 = MyObj1.objects.filter (some_field__gte = value) - qs2 d'altra parte è in realtà una relazione M2M tra una certa istanza MyObj2 e istanze MyObj1 Ho pensato di chiedere su QuerySets, poiché penso che la risposta sarebbe applicabile anche a myobj2_instance.myobj1. – Jonathan

risposta

1

Penso che per operazioni come questa è necessario valutarle. Quindi puoi chiamare list() su di loro e lavorarci sopra con le comuni operazioni di lista dei python!

3

È possibile utilizzare Q object.

La sintassi potrebbe essere qualcosa di simile:

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

Probabilmente si possono effettuare l'ottimizzazione in base alle vostre reali esigenze e ottenere la quantità di db colpisce verso il basso (in questo momento è 3), ma questo dovrebbe iniziare.

+0

+1 per farlo bene con i set di query, ma immagino che stia colpendo il db una volta di più che aggiungere liste! Immagino che il metodo che preferisci dipenda da se vuoi un qs non valutato o meno db hit! –

+0

Dati i parametri effettivi dei due 'QuerySet' originali dovresti essere in grado di includere quei parametri negli oggetti' Q' e scendere a un db hit – Zach

12

Tornando a django's documentation, è possibile:

new_query_set = query_set_1 | query_set_2 

Questo funziona come un OR logico che in realtà è aggiunta senza duplicati. Questo risponde all'aspetto aggiuntivo e AFAIK non ha colpito il db a tutti!

new_query_set = query_set_1 & query_set_2 

Questo funziona come un AND logico.

Manca ancora il modo in cui sottrarre QuerySets. È difficile per me credere che questo non sia stato trattato elegantemente dalla comunità ...

+2

ancora in cerca del modo calssy di sottrarre il set di query – philgo20

+0

usando .exclude() ? – mccc

12

Sottrarre un QuerySet da un altro QuerySet usando lo stesso modello.

Questo funziona - ma è probabilmente lentamente

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

Leggere le considerazioni sulle prestazioni nella documentazione django:

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

+0

Questo funziona solo durante la costruzione di QuerySet, la domanda riguarda ** ** QuerySets esistenti. Come si fa a fare qs1- qs2 quando esistono già come querysets. – Curtwagner1984

+0

La modifica di un queryset esistente è una nozione che non ha molto senso in django. Fai questo: 'q = Blog.objects.filter (pk__in = q1) .exclude (pk__in = q2)' – DylanYoung

4

Dal Django 1.11, querysets hanno union(), intersection() and difference() methods.

E 'anche possibile utilizzare | and & operators con QuerySets (non sono riuscito a trovare un riferimento a questo in e documenti, quindi immagino che union() e intersection() siano il modo preferito per combinare due set di query.

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. 

È anche possibile utilizzare Q() objects che come querysets implementare | e &, e inoltre l'inversione dell'operatore ~

Problemi correlati