Фильтрация пустых или пустых имен в наборе запросов

305

У меня есть first_name, last_name и псевдоним (необязательно), которые мне нужно найти. Поэтому мне нужен запрос, чтобы дать мне все имена, у которых есть набор псевдонимов.

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

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

Итак, что эквивалентно приведенному выше?

Теги:
django-models
filter
null
django-queryset

4 ответа

613
Лучший ответ

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

Name.objects.exclude(alias__isnull=True)

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

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

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

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

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

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

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

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

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

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

Подробнее см. эту страницу и эту страницу в документах Django.

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

  • 5
    Я считаю , что ваша правка неправильно: Цепной фильтр не будет автоматически создавать SQL OR (только в этом случае), он производит SQL AND . См. Эту страницу для справки: docs.djangoproject.com/en/dev/topics/db/queries/… Преимущество цепочки заключается в том, что вы можете смешивать exclude и filter для моделирования сложных условий запроса. Если вы хотите смоделировать реальный SQL OR вы должны использовать объект Django Q: docs.djangoproject.com/en/dev/topics/db/queries/… Пожалуйста, отредактируйте ваши изменения, чтобы отразить это, поскольку ответ сильно вводит в заблуждение, так как стоит.
  • 1
    @shezi: Я имел в виду это скорее как аналогию - я не имел в виду, что реальный код SQL гарантированно использует OR для объединения условий. Я отредактирую свой ответ, чтобы уточнить.
Показать ещё 3 комментария
31

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

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

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

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

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

26
Name.objects.filter(alias__gt='',alias__isnull=False)
  • 1
    Я не уверен, но я думаю, что alias__isnull=False является избыточным. Если поле имеет значение Null то оно обязательно будет исключено первым предложением?
  • 0
    Помимо моего предыдущего комментария / вопроса, я думаю, что позитивной логике здесь легче следовать, чем в некоторых других ответах.
Показать ещё 1 комментарий
3

Из Django 1.8,

from django.db.models.functions import Length

Name.objects.annotate(alias_length=Length('alias')).filter(alias_length__gt=0)
  • 2
    Это похоже на «то, что вы можете сделать», а не то, что вы должны делать. Это значительно увеличивает сложность запроса за две простые проверки.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню