404を返さずにオブジェクトがdjangoビューに存在するかどうかを検証する正しい方法は何ですか?


91

オブジェクトが存在するかどうかを確認し、オブジェクトを返す必要があります。次に、それに基づいてアクションを実行します。404を返さずにそれを行う正しい方法は何ですか?

try:
    listing = RealEstateListing.objects.get(slug_url = slug)
except:
    listing = None

if listing:

ラシエル、他の答えを受け入れることを検討することを提案できますか?これはこれを行う正しい方法のようであり、受け入れられた回答よりもかなり多く賛成されています。
Azendale 2015年

1
私はそれを考えることができますが、存在するのは2010年5月17日にリリースされたDjango 1.2で導入されました。Exists()がそれを行うための最良の方法と見なされている場合、2番目の答えを選択することは意味的に正しいと思いますか?
Rasiel

Rasiel、それが当時の正解だったのは理にかなっています。しかし、stackoverflowサイトは、サイトが人々の問題の解決策を見つけているのと同じくらい、最良の回答で一連の良い/公式の質問を作成することと同じように見えます。したがって、現在「公式に正しい」答えとなるものを選択するという私の提案。
Azendale 2015年

はであるif listing:必要がありelse:ます。
クロニアル2015年

回答:


116

あなたが404を与えられないなら、私は404ラッパーを使用しません。それは意図の誤用です。代わりに、DoesNotExistをキャッチしてください。

try:
    listing = RealEstateListing.objects.get(slug_url=slug)
except RealEstateListing.DoesNotExist:
    listing = None

1:あなたは404たくない場合は、[はい、これは、受け入れられたものよりも、よりよい解決策である
カール・マイヤー

うん、これはより良い解決策のようです
Rasiel

3
このソリューションexists()は、オブジェクトを操作する必要がある場合よりもうまく機能します。
SaeX 2015年

2
追加したいvalues_list('id', flat=True)です。存在するかどうかを確認する必要がある場合listing = RealEstateListing.objects.values_list('id', flat=True).get(slug_url=slug)
エラフアン2016年

この構文について奇妙なのRealEstateListing.DoesNotExistは、オブジェクト自体ではなくモデルを参照していることです。なぜそうではないのRealEstateListing.objects.get(slug_url=slug).DoesNotExistですか?
Maxim Vallee

198

次のこともできます:

if not RealEstateListing.objects.filter(slug_url=slug).exists():
    # do stuff...

try: except:ブロックを使用する方が明確な場合もあれば、ワンライナーexists()でコードをより見やすくする場合もあります...すべてはアプリケーションロジックに依存します。


7
.exists()の方が高速です:docs.djangoproject.com/en/dev/ref/models/querysets/#exists
fjsj

7
これは良い方法であると答えていなければならない
Jharwood

3
exists()動作しないと思いますよget()ね?
Eduard Luca

8
このソリューションは、問題のオブジェクトを使用しない場合にのみ有効であることに注意してください。それ以外の場合(OPの状況と同様)、それは誤りであり、受け入れられているソリューションよりもかなり遅くなりget()ます。後で行うと、2番目のクエリがデータベースに送信されます。
クロニアル2015年

1
オブジェクトが存在する場合は、その存在をチェックして何かを行う場合は、を優先try-exceptexists()ます。
Jithin Pavithran 16

7
listing = RealEstateListing.objects.filter(slug_url=slug).first() 

2
これは、潜在的なオブジェクトを後で使用する必要がある場合に最適なソリューションです。割り当てが1つだけ必要で、try / exceptブロックを使用する必要がないためです。後で簡単に存在をテストできることに注意してくださいif listing:
マイケル・ヘイズ

try / exceptを回避することは悪い習慣です。ソフトウェア開発の最も重要な側面の1つは、例外を制御できることです。これにより、優れたユーザーエクスペリエンスを提供できます。何かが正しく機能していない場合は、人々に知らせてください。第二; QuerySetの存在をテストする場合は.exists()を使用します。それ以外の場合はオブジェクトです。主キーを使用して存在をテストします... if object.pk:// run code()このクエリは、オブジェクトのすべてのデータを取得するよりもはるかに高速です。存在するかどうかを知りたいだけです。
Wolfgang Leon

2
try / exceptとを使用した解決策はすでにありました.exists()。SOでは、物事をどのように実行するかについて複数の異なる答えを持つことが良い考えだと思います。おそらく、オブジェクトが存在する場合はそれも使用したい人に向いています。try / exceptを回避する必要があるかどうかを判断するためのルールは作成しません。非常にコンパクトなコードを作成したいだけの場合など、良いこともあれば悪いこともあります。
Henrik Heino 2018年

0

私は次のようにそれを簡単にするでしょう:

listing = RealEstateListing.objects.filter(slug_url=slug)
if listing:
    # do stuff

try / catchの必要はないと思います。結果に複数のオブジェクトが含まれる可能性がある場合は、ユーザーHenrik Heinoが示すようにfirst()を使用します


クエリセットで.first()または条件付きで.first()を実行しない限り、これは常にTrueを返します。
B.Adler
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.