2011-01-27 5 views
27

Ho un capriccio con Django filtraggio set di query (?):Django objects.filter() values_list() vs lista di pitone di comprensione per la query __in

ipdb> MagazineIssue.objects.filter(id__in=l_magazines.values_list('id')) 
Out[0]: [] 

o

ipdb> MagazineIssue.objects.filter(id__in=[l_magazine.id for l_magazine in l_magazines]) 
Out[0]: [<MagazineIssue: Architecture Australia, Jan 1995 (#1)>] 

e

ipdb> l_magazines.values_list('id') 
Out[0]: [(1,)] 
ipdb> [l_magazine.id for l_magazine in l_magazines] 
Out[0]: [1] 

quindi, come usare values_list()? (per produrre):

[1] 

oppure la lista dei pitoni è la 'strada da percorrere'?

risposta

56

Prova l_magazines.values_list('id', flat=True). Questo restituisce una lista di id invece di una lista di tuple di id singole.

+5

C'è una differenza di prestazioni? – Marcin

+3

Enorme. values_list è waay più veloce. flat = true lo rende ancora più veloce perché python non ha bisogno di creare un'istanza di tutti gli oggetti nell'elenco, vengono restituiti solo i valori del database. –

+1

per chiarire, è più veloce perché Django riconosce che stiamo usando un queryset come argomento per un queryset, quindi li combina entrambi in una singola query - non valuta prima il queryset 'values_list' in una lista! – Anentropic

2

Una cosa da notare è che c'è una differenza nel comportamento dei valori/values_list da una lista di comprensione:

  • valori/values_list produrrà il valore effettivo memorizzato nel campo, cioè, solo la id (non l'intero oggetto)
  • se il valore è una chiave esterna e si dispone delle relazioni appropriate impostate nel modello, la comprensione della lista fornirà l'oggetto a cui fa riferimento la chiave esterna.

La scelta di quella sbagliata causerà un numero eccessivo di riscontri di database o di inutili deviazioni, a seconda di cosa si sta tentando di fare.

Problemi correlati