Djangoで空のクエリセットを確認する


183

クエリが結果を返したかどうかを確認するために推奨されるイディオムは何ですか?
例:

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

これをチェックする方法はいくつかあると思いますが、経験豊富なDjangoユーザーがそれをどのように行うかを知りたいのです。ドキュメントのほとんどの例では、何も見つからなかった場合を無視しています...

回答:


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

5
これは、ドキュメントでも好まれているようです。たとえば、次のとおり
en

1
@Wtower参照するコードは、フィルタリング式がレコードにヒットしない場合は404を発生させる、またはlistレコードがある場合は結果を生成するという契約を結んでいます。そこにあるコードはデータベースに一度だけヒットします。使用する場合、exist()またはcount()最初にレコードが返されるかどうかを確認するために、データベースに2回アクセスします(1回は確認、1回はレコードを取得するため)。これは特定の状況です。それはでそれを必要としない一般的な場合、クエリがレコードを返すかどうかを知るための好ましい方法は、使用しないでif queryset:...
ルイ

1
@Louis私が参照するコードif not my_objects:は、ドキュメントでこれがどのように行われるかを示すための行を含む例にすぎません。他のすべては全く無関係なので、私はあなたのポイントを取得しません。彼らは千のクエリを作成することもできますが、これはこの回答のポイントではないので完全に無関係であり、同意します。
Wtower 2015年

1
@Wtowerこれは動作の説明すぎず、クエリセットに要素が存在するかどうかを確認する好ましい方法ではありません。クエリセットでlist()を実行すると、クエリセットのすべてのオブジェクトがフェッチされます。これは、返される行数が多い場合に2回クエリするよりも悪くなります。get_object_or_404
minmaxavg

1
より詳細な回答については、以下の@ leonid-shvechikovの回答をご覧ください。qs .exists()が評価されない場合は、使用する方が効率的です。
guival

191

バージョン1.2以降、DjangoにはQuerySetがあります。最も効率的なexists()メソッド:

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

ただし、とにかくQuerySetを評価する場合は、以下を使用することをお勧めします。

if orgs:
   ...

詳細については、QuerySet.exists()のドキュメントをご覧ください。


.exists()は.filter()専用ですが、.get()には何かありますか?
ロール

.getクエリセットを返しません。オブジェクトを返します。だから、そのためにグーグル
Aseem

大規模なQuerySet
Nathan Jones

16

膨大な数のオブジェクトがある場合、これは(時には)はるかに高速になる可能性があります。

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

私が巨大なデータベースで取り組んでいるプロジェクトでnot orgsは、400ミリ秒以上、250ミリ秒orgs.count()です。私の最も一般的な使用例(結果がある場合)では、この手法はそれを20ミリ秒未満にすることがよくあります。(私が見つけた1つのケース、それは6でした。)

もちろん、結果を見つけるためにデータベースがどこまで探す必要があるかに応じて、はるかに長くなる可能性があります。または、それをすばやく見つけた場合はさらに速くなります。YMMV。

編集:これ多くのorgs.count()場合、結果が見つからない場合よりも遅くなります。特に、フィルタリングしている条件がまれな場合です。その結果、ビューが存在することを確認するか、Http404をスローする必要があるビュー関数で特に役立ちます。(希望するところでは、人々はより頻繁に存在するURLを求めています。)


10

クエリセットが空かどうかを確認するには:

if orgs.exists():
    # Do something

または、クエリセットの最初の項目を確認できます。存在しない場合は、次を返しNoneます。

if orgs.first():
    # Do something

7
if orgs.exists()この回答の約5年前に提供された回答で覆われていました。この答えがおそらく新しいテーブルにもたらす唯一のものはif orgs.first()です。(でもこの議論の余地がある:それはやって実質的に異なるorgs[0] 提案あまりにも約5年前?)あなたは答えの一部を開発するべきである:一つはこれをしたいと思うとき、代わりに他のソリューションは、以前の提案しましたか?
ルイ・

9

最も効率的な方法(django 1.2以前)は次のとおりです。

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

5
.exists()の方が効率的です
dzida

5
ただし、コメントの数か月後に.exists()が追加され、そのAPIを組み込んだDjango 1.2が約8か月後にリリースされました。しかし、反対票を投じて事実を確認する手間を省いてくれてありがとう。
Bartosz

4
申し訳ありませんが、回答をより正確にして肯定的な投票を行うために、回答を少し編集しました。
dzida 2012

4

述語に同意しません

if not orgs:

そのはず

if not orgs.count():

かなり大きな結果セット(約15万件)でも同じ問題が発生していました。演算子はQuerySetでオーバーロードされないため、結果は実際にはチェックが行われる前にリストとしてアンパックされます。私の場合、実行時間は3オーダー減少しました。


6
__nonzero__はすでにQuerySetでオーバーロードされています。結果がキャッシュされない場合(クエリセットの最初の使用では決してありません)、__ nonzero__の動作はクエリセットのすべての要素を反復処理することです。セットが大きい場合、これは非常に悪いです。
hedleyroos、2011

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.