2015-11-04 9 views
7

Voglio creare una parte di query di filtro Django ORM dinamicly, ora posso fare:sempre vera Q oggetto

if some: 
    Obj.filter(
     some_f1=some_v1, 
     f1=v1, 
     f2=v2, 
     f3=v3, 
     f4=v4, 
     ... 
    ) 
else: 
    Obj.filter(
     f1=v1, 
     f2=v2, 
     f3=v3, 
     f4=v4, 
     ... 
    ) 

voglio qualcosa senza codice di duplicare in questo modo:

Obj.filter(
    Q(some_f1=some_v1) if some else True, # what to use instead of True? 
    f1=v1, 
    f2=v2, 
    f3=v3, 
    f4=v4, 
    ... 
) 
+1

C'è un modo per fare un oggetto Q sempre falso? – Flimm

+0

Non funziona. Ho creato la domanda per chiedere come creare un oggetto False Q sempre http://stackoverflow.com/q/35893867/247696 – Flimm

risposta

6

Ecco un modo hacky per ottenere un sempre vero oggetto D:

always_true = ~Q(pk=None) 

Questo dipende dal fatto che la chiave primaria non può essere nulla.

3

Prova questo ;

conditions = {'f1':f1,'f2':f2, 'f3':f3} 
if some: 
    conditions['some_f1'] = some_v1 

Obj.objects.filter(**conditions) 
+3

"key" è un nome fuorviante qui. Forse 'condizioni'? –

0

Sulla base this risposta che possiamo fare argomento condizionale passando

Obj.filter(
    *((Q(some_f1=some_v1),) if some else()),  
    f1=v1, 
    f2=v2, 
    f3=v3, 
    f4=v4, 
    ... 
) 

Quindi, se some è True aggiungiamo tuple (Q(some_f1=some_v1),) all'elenco argomenti, in altro caso aggiungiamo tupla vuota (), anche abbiamo bisogno per avvolgerlo in *(), come sempre quando passiamo tupla di argomenti senza parole chiave

+0

Sarebbe bello se aggiungessi qualche commento sulla logica alla base di questo trucco (: – FallenAngel

+3

Personalmente, penso che spostare la logica if else dal 'filter()' renda più facile la lettura, ma se preferisci questo stile, puoi usare un 'Q()' senza argomenti: 'Q (some_f1 = some_v1) se condizione else Q()'. Questo evita la necessità di '* args' decompressione. – Alasdair

+0

Alasdair, il tuo commento è la risposta, per favore pubblica – user3479125

1

come Alasdair ha risposto in un commento:

Obj.filter(
    Q(some_f1=some_v1) if some else Q(), 
    f1=v1, 
    f2=v2, 
    f3=v3, 
    f4=v4, 
    ... 
) 
+2

Si noti che 'Q()' non è in realtà un oggetto Q sempre vero, è un oggetto Q vuoto, ad esempio, sia 'Foobar.objects.filter (Q())' che 'Foobar.objects.exclude (Q ()) 'return all objects. – Flimm

+1

Per seguire il commento di @ Flimm, credo che' Q (pk__isnull = False) 'possa funzionare come l'oggetto Q sempre vero invece di' Q() '. – Alasdair

0

Dal QuerySets are lazy, è possibile creare il filtro predefinito e quindi aggiungere altre basi alle condizioni. Django non eseguire la query fino a quando il QuerySet viene valutata (per esempio, l'iterazione attraverso di essa in un ciclo for)

filtered_objects = Obj.filter(
    some_f1=some_v1, 
    f1=v1, 
    f2=v2, 
    f3=v3, 
    f4=v4, 
    ... 
) 
if some: 
    filtered_objects.filter(some_f1=some_v1)