Проверка пустого набора запросов в 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 сделает это.
Большинство примеров в документах просто игнорируют случай, когда ничего не было найдено...
7 ответов:
начиная с версии 1.2, Django имеет QuerySet.существует() метод, который является наиболее эффективным:
if orgs.exists(): # Do this... else: # Do that...
но если вы все равно собираетесь оценивать QuerySet, лучше использовать:
if orgs: ...
для получения дополнительной информации читать QuerySet.существует() документация.
если у вас есть огромное количество объектов, это может (иногда) быть гораздо быстрее:
try: orgs[0] # If you get here, it exists... except IndexError: # Doesn't exist!
над проектом я работаю с огромной базой данных,
not orgs
- это 400+ мс иorgs.count()
составляет 250 мс. в моих наиболее распространенных случаях использования (те, где есть результаты), этот метод часто получает это до 20 мс. (один случай я нашел, это было 6.)может быть гораздо дольше, конечно, в зависимости от того, как далеко база данных должна искать, чтобы найти результат. Или даже быстрее, если он его найдет быстро; YMMV.
редактировать: этот будет часто быть медленнее, чем
orgs.count()
если результат не найден, особенно если условие, которое вы фильтруете, является редким; в результате это особенно полезно в функциях представления, где вам нужно убедиться, что представление существует или бросить Http404. (Где, хотелось бы надеяться, люди просят URL-адреса, которые существуют чаще, чем нет.)
чтобы проверить пустоту queryset:
if orgs.exists(): # Do something
или вы можете проверить первый элемент в queryset, если он не существует, он вернет
None
:if orgs.first(): # Do something
Я не согласен с предикатом
if not orgs:
Он должен быть!--3-->
if not orgs.count():
у меня была такая же проблема с довольно большим набором результатов (~150k результатов). Оператор не перегружается в QuerySet,поэтому результат фактически распаковывается в виде списка перед проверкой. В моем случае время исполнения сократилось на три ордера.
самый эффективный способ (до django 1.2) это:
if orgs.count() == 0: # no results else: # alrigh! let's continue...
можно использовать
len
илиlast()
if not len(orgs): # if queryset is empty do something
if not orgs.last(): # if queryset is empty do something
Comments