2009-05-10 9 views

risposta

614

Si potrebbe fare questo:

Name.objects.exclude(alias__isnull=True) 

Se è necessario escludere i valori nulli e stringhe vuote, il modo migliore per farlo è di concatenare le condizioni in questo modo:

Name.objects.exclude(alias__isnull=True).exclude(alias__exact='') 

Il concatenamento di questi metodi insieme controlla praticamente ogni condizione in modo indipendente: nell'esempio sopra, escludiamo le righe dove alias è nullo o una stringa vuota, quindi tu ottenere tutti gli oggetti Name con un campo alias non nullo e non vuoto. L'SQL generato sarebbe simile:

SELECT * FROM Name WHERE alias IS NOT NULL AND alias != "" 

È inoltre possibile passare più argomenti per una singola chiamata a exclude, che garantirebbe che solo gli oggetti che soddisfano ogni condizione di ottenere esclusa:

Name.objects.exclude(some_field=True, other_field=True) 

Qui, le righe in cui some_fieldeother_field sono true vengono escluse, quindi otteniamo tutte le righe in cui entrambi i campi non sono vere. Il codice SQL generato apparirebbe un po 'come questo:

SELECT * FROM Name WHERE NOT (some_field = TRUE AND other_field = TRUE) 

In alternativa, se la logica è più complesso di quello, è possibile utilizzare di Django Q objects:

from django.db.models import Q 
Name.objects.exclude(Q(alias__isnull=True) | Q(alias__exact='')) 

Per ulteriori informazioni vedere this page e this page in i documenti di Django.

Per inciso: i miei esempi SQL sono solo un'analogia: il codice SQL generato effettivo probabilmente avrà un aspetto diverso. Avrai una comprensione più profonda di come funzionano le query Django guardando effettivamente l'SQL che generano.

+3

Credo che la tua modifica sia errata: il filtro concatenamento NON crea automaticamente un 'OR' SQL' (solo in questo caso), produce un' ED' SQL. Vedere questa pagina per riferimento: https://docs.djangoproject.com/en/dev/topics/db/queries/#chaining-filters Il vantaggio della concatenazione è che è possibile mescolare 'exclude' e' filter' per modellare condizioni di query complicate. Se si desidera modellare un vero 'OR' SQL' è necessario utilizzare un oggetto Django Q: https://docs.djangoproject.com/en/dev/topics/db/queries/#complex-lookups-with-q- oggetti Si prega di modificare la vostra modifica per riflettere questo, in quanto la risposta è gravemente fuorviante così com'è. – shezi

+1

@shezi: intendevo più un'analogia - non intendevo dire che il codice SQL reale è garantito per utilizzare un 'OR' per fondere le condizioni. Modificherò la mia risposta per chiarire. –

+0

Ricorda che ci sono diversi modi per rappresentare questa logica - per esempio, 'NOT (A AND B)' è equivalente a 'NOT A OR NOT B'. Penso che ciò renda le cose confuse ai nuovi sviluppatori di Django che conoscono SQL ma non hanno familiarità con gli ORM. –

31

In primo luogo, i documenti Django consigliano vivamente di non utilizzare valori NULL per campi basati su stringhe come CharField o TextField. Leggi la documentazione per la spiegazione:

https://docs.djangoproject.com/en/dev/ref/models/fields/#null

Soluzione: È inoltre possibile concatenare insieme i metodi su querysets, credo. Prova questo:

Name.objects.exclude(alias__isnull=True).exclude(alias="") 

Questo dovrebbe darti il ​​set che stai cercando.

+7

Un link a dove dice che sarebbe stato bello. https://docs.djangoproject.com/en/dev/ref/models/fields/#null – mpen

28
Name.objects.filter(alias__gt='',alias__isnull=False) 
+1

Non sono sicuro, ma penso che la condizione 'alias__isnull = False' sia ridondante. Se il campo è 'Null' sicuramente sarà escluso dalla prima clausola? – Bobble

+0

A parte il mio precedente commento/domanda, penso che la logica positiva qui sia più facile da seguire che in alcune delle altre risposte. – Bobble

+0

@Bobble che dipenderebbe dall'implementazione del database - [l'ordine è delegato al database] (https://docs.djangoproject.com/en/1.10/ref/models/querysets/#latest) – wpercy

3

Da Django 1.8,

from django.db.models.functions import Length 

Name.objects.annotate(alias_length=Length('alias')).filter(alias_length__gt=0) 
+0

Questo sembra un " qualcosa che * puoi * fare ", non qualcosa che dovresti * fare *. Sbaglia in modo significativo la complessità della query su due semplici controlli. – Oli