2009-05-10 2 views
320

У меня есть имя_имя, last_name & псевдоним (необязательно), который мне нужно найти. Итак, мне нужен запрос, чтобы дать мне все имена, у которых есть псевдоним.Фильтрация для пустых или NULL имен в запросе

Только если я мог бы сделать:

Name.objects.filter(alias!="") 

Итак, что эквивалентно выше?

ответ

614

Вы можете сделать это:

Name.objects.exclude(alias__isnull=True) 

Если необходимо исключить нулевые значения и пустые строки, предпочтительный способ сделать так, чтобы цепь вместе условия, как так:

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

Объединение этих методов вместе в основном проверяет каждое условие независимо: в приведенном выше примере мы исключаем строки, в которых alias либо имеет значение null , либо пустую строку, поэтому вы получаете все объекты Name, у которых есть не пустое, не пустое поле alias. Сгенерированный SQL будет выглядеть примерно так:

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

Вы также можете передать несколько аргументов в одном вызове exclude, который будет гарантировать, что только объекты, которые отвечают каждый условие получить исключены:

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

Здесь строки, в которых иother_field истинны, исключаются, поэтому мы получаем все строки, в которых оба поля не являются истинными. Сгенерированный SQL-код будет выглядеть немного как это:

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

В качестве альтернативы, если ваша логика является более сложной, чем вы могли бы использовать Джанго Q objects:

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

Для получения дополнительной информации см this page и this page в документы Django.

Как в стороне: мои примеры SQL - это просто аналогия - реально созданный код SQL, вероятно, будет отличаться. Вы получите более глубокое представление о том, как работают Django-запросы, фактически просматривая SQL, который они создают.

+3

Я считаю, что ваше изменение неверно: Цепочный фильтр НЕ автоматически создает SQL 'OR' (только в этом случае), он создает SQL' AND'. См. Эту страницу для справки: https://docs.djangoproject.com/en/dev/topics/db/queries/#chaining-filters Преимущество цепочки заключается в том, что вы можете смешивать 'exclude' и' filter' с моделью сложных условий запроса. Если вы хотите смоделировать настоящий SQL 'OR', вы должны использовать объект Django Q: https://docs.djangoproject.com/en/dev/topics/db/queries/#complex-lookups-with-q- объекты Пожалуйста, отредактируйте свое редактирование, чтобы отразить это, так как ответ серьезно вводит в заблуждение, поскольку он стоит. – shezi

+1

@shezi: Я имел в виду это скорее как аналогию - я не имел в виду, что реальный код SQL гарантированно использует «OR» для слияния условий. Я отредактирую свой ответ, чтобы уточнить. –

+0

Имейте в виду, что есть разные способы представления этой логики - например, 'NOT (A AND B)' эквивалентно 'NOT A ИЛИ NOT B'. Я думаю, что это путает новых разработчиков Django, которые знают SQL, но не знакомы с ORM. –

31

Во-первых, документы Django настоятельно рекомендуют не использовать значения NULL для строковых полей, таких как CharField или TextField. Прочитайте документацию для объяснения:

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

Решение: Вы также можете приковать совместно методы QuerySets, я думаю. Попробуйте следующее:

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

Это должно дать вам комплект, который вы ищете.

+7

Ссылка на то, где говорится, что было бы хорошо. https://docs.djangoproject.com/en/dev/ref/models/fields/#null – mpen

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

Я не уверен, но я думаю, что условие alias__isnull = False избыточно. Если поле «Null» конечно, оно будет исключено из первого предложения? – Bobble

+0

Помимо моего предыдущего комментария/вопроса, я думаю, что положительная логика здесь легче следовать, чем в некоторых других ответах. – Bobble

+0

@Bobble, который будет зависеть от реализации базы данных - [заказ делегирован в базу данных] (https://docs.djangoproject.com/en/1.10/ref/models/querysets/#latest) – wpercy

3

От Django 1.8,

from django.db.models.functions import Length 

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

Это похоже на " то, что вы * можете * сделать ", а не то, что вы * должны делать. Это значительно расцветает сложность запроса по двум простым проверкам. – Oli