Какова рекомендуемая идиома для проверки того, вернул ли запрос какие-либо результаты?
Пример:
orgs = Organisation.objects.filter(name__iexact = 'Fjuk inc')
# If any results
# Do this with the results without querying again.
# Else, do something else...
Я предполагаю, что есть несколько способов проверить это, но я хотел бы знать, как это сделал бы опытный пользователь Django. Большинство примеров в документах просто игнорируют случай, когда ничего не найдено...
if not orgs:
# Do this...
else:
# Do that...
Начиная с версии 1.2, Django имеет QuerySet. exists() метод, который является наиболее эффективным:
if orgs.exists():
# Do this...
else:
# Do that...
Но если вы все равно оцените QuerySet, лучше использовать:
if orgs:
...
Для получения дополнительной информации прочитайте документацию QuerySet.exists().
Если у вас огромное количество объектов, это может (время от времени) быть намного быстрее:
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-адреса, которые существуют чаще, чем нет.)
Чтобы проверить пустоту набора запросов:
if orgs.exists():
# Do something
или вы можете проверить первый элемент в наборе запросов, если он не существует, он вернет None
:
if orgs.first():
# Do something
if orgs.exists()
был покрыт ответом, который был предоставлен примерно за 5 лет до этого. Единственное, что этот ответ приносит в таблицу, которая, возможно, является новой, это if orgs.first()
. (Даже это спорно: он существенно отличается от делать orgs[0]
предложил около 5 лет назад тоже?) Вы должны развивать эту часть ответа: когда бы один хочет сделать это вместо других решений , предложенных ранее?
Наиболее эффективным способом (до django 1.2) является следующее:
if orgs.count() == 0:
# no results
else:
# alrigh! let continue...
Я не согласен с предикатом
if not orgs:
Это должно быть
if not orgs.count():
У меня была такая же проблема с довольно большим набором результатов (~ 150 тыс. результатов). Оператор не перегружен в QuerySet, поэтому результат фактически распаковывается как список перед проверкой. В моем случае время выполнения сократилось на три порядка.
Вы также можете использовать это:
if(not(orgs)): #if orgs is empty else: #if orgs is not empty
list
результатов, если есть записи. Код там попадет в базу данных только один раз. Если бы они использовалиexist()
илиcount()
чтобы сначала проверить, будут ли возвращены записи, они дважды попадут в базу данных (один раз, чтобы проверить, один раз, чтобы получить записи). Это конкретная ситуация. Это не означает, что в общем случае предпочтительным способом узнать, будет ли запрос возвращать записи, является использование doif queryset:...