Проверка пустого набора запросов в Django

Какова рекомендуемая идиома для проверки того, вернул ли запрос какие-либо результаты?
Пример:

orgs = Organisation.objects.filter(name__iexact = 'Fjuk inc')
# If any results
    # Do this with the results without querying again.
# Else, do something else...

Я предполагаю, что есть несколько способов проверить это, но я хотел бы знать, как это сделал бы опытный пользователь Django. Большинство примеров в документах просто игнорируют случай, когда ничего не найдено...

Ответ 1

if not orgs:
    # Do this...
else:
    # Do that...

Ответ 2

Начиная с версии 1.2, Django имеет QuerySet. exists() метод, который является наиболее эффективным:

if orgs.exists():
    # Do this...
else:
    # Do that...

Но если вы все равно оцените QuerySet, лучше использовать:

if orgs:
   ...

Для получения дополнительной информации прочитайте документацию QuerySet.exists().

Ответ 3

Если у вас огромное количество объектов, это может (время от времени) быть намного быстрее:

try:
    orgs[0]
    # If you get here, it exists...
except IndexError:
    # Doesn't exist!

В проекте, над которым я работаю с огромной базой данных, not orgs составляет 400+ мс, а orgs.count() - 250 мс. В моих наиболее распространенных случаях использования (те, где есть результаты), этот метод часто получает до менее 20 мс. (Один случай, который я нашел, это было 6.)

Может быть намного длиннее, конечно, в зависимости от того, как далеко должна искать база данных, чтобы найти результат. Или даже быстрее, если он найдет одно быстро; YMMV.

EDIT: это часто будет медленнее, чем orgs.count(), если результат не найден, особенно если условие, на которое вы фильтруете, является редким; в результате, это особенно полезно в функции, где вам нужно убедиться, что существует представление или выбрасывать Http404. (Где, можно надеяться, люди просят URL-адреса, которые существуют чаще, чем нет.)

Ответ 4

Чтобы проверить пустоту набора запросов:

if orgs.exists():
    # Do something

или вы можете проверить первый элемент в наборе запросов, если он не существует, он вернет None:

if orgs.first():
    # Do something

Ответ 5

Наиболее эффективным способом (до django 1.2) является следующее:

if orgs.count() == 0:
    # no results
else:
    # alrigh! let continue...

Ответ 6

Я не согласен с предикатом

if not orgs:

Это должно быть

if not orgs.count():

У меня была такая же проблема с довольно большим набором результатов (~ 150 тыс. результатов). Оператор не перегружен в QuerySet, поэтому результат фактически распаковывается как список перед проверкой. В моем случае время выполнения сократилось на три порядка.

Ответ 7

Вы также можете использовать это:

if(not(orgs)): #if orgs is empty else: #if orgs is not empty