回答:
これを行うための「組み込み」の方法はありません。Djangoは毎回DoesNotExist例外を発生させます。pythonでこれを処理する慣用的な方法は、try catchでラップすることです。
try:
go = SomeModel.objects.get(foo='bar')
except SomeModel.DoesNotExist:
go = None
私がやったことは、models.Managerをサブクラス化して、safe_get
上記のようなコードを作成し、モデルにそのマネージャーを使用することです。そのように書くことができます:SomeModel.objects.safe_get(foo='bar')
。
SomeModel.objects.filter(foo='bar').first()
では、これを使用して最初の一致を返すか、Noneを返すことができます。次のようなインスタンスがいくつかある場合、失敗しませんqueryset.get()
filter().first()
私は例外が行く方法だと思います。
django 1.6以降では、first()メソッドを次のように使用できます。
Content.objects.filter(name="baby").first()
get()
DoesNotExist
指定されたパラメーターのオブジェクトが見つからない場合は、例外が発生します。この例外は、モデルクラスの属性でもあります。DoesNotExist
から、例外継承django.core.exceptions.ObjectDoesNotExist
あなたは例外をキャッチしNone
て行くために割り当てることができます。
from django.core.exceptions import ObjectDoesNotExist
try:
go = Content.objects.get(name="baby")
except ObjectDoesNotExist:
go = None
このためのジェネリック関数を作成できます。
def get_or_none(classmodel, **kwargs):
try:
return classmodel.objects.get(**kwargs)
except classmodel.DoesNotExist:
return None
以下のようにこれを使用してください:
go = get_or_none(Content,name="baby")
一致するエントリがない場合、goはNoneになり、それ以外はContentエントリを返します。
注:name = "baby"に対して複数のエントリが返された場合は、MultipleObjectsReturned例外が発生します。
あなたはこの方法でそれを行うことができます:
go = Content.objects.filter(name="baby").first()
go変数は、必要なオブジェクトまたはNoneのいずれかになります
参照:https : //docs.djangoproject.com/en/1.8/ref/models/querysets/#django.db.models.query.QuerySet.first
物事を簡単にするために、ここに素晴らしい返信からの入力に基づいて、私が書いたコードのスニペットを示します。
class MyManager(models.Manager):
def get_or_none(self, **kwargs):
try:
return self.get(**kwargs)
except ObjectDoesNotExist:
return None
そして、あなたのモデルでは:
class MyModel(models.Model):
objects = MyManager()
それでおしまい。これで、MyModel.objects.get()とMyModel.objetcs.get_or_none()ができました。
あなたはexists
フィルターと一緒に使うことができます:
Content.objects.filter(name="baby").exists()
#returns False or True depending on if there is anything in the QS
それが存在するかどうかを知りたいだけの場合の代替手段
exists()
with if
句とともに使用され、dbにダブルヒットを引き起こします。他の人を助けるためにコメントを残しておきます。
ビューのさまざまなポイントで例外を処理することは、非常に煩雑になる可能性があります。models.pyファイルで、次のようにカスタムModel Managerを定義することについてはどうでしょうか。
class ContentManager(model.Manager):
def get_nicely(self, **kwargs):
try:
return self.get(kwargs)
except(KeyError, Content.DoesNotExist):
return None
そしてそれをコンテンツモデルクラスに含めます
class Content(model.Model):
...
objects = ContentManager()
このようにして、ビューで簡単に処理できます。
post = Content.objects.get_nicely(pk = 1)
if post:
# Do something
else:
# This post doesn't exist
return self.get(**kwargs)
た。答えに誤りがあると言っているのではなく、それを新しいバージョンで使用しようとしている人のためのヒント(または他のバージョンでそれが私のために機能しないようにしたもの)にすぎません。
使うのは悪くないと思います get_object_or_404()
from django.shortcuts import get_object_or_404
def my_view(request):
my_object = get_object_or_404(MyModel, pk=1)
この例は、次と同等です。
from django.http import Http404
def my_view(request):
try:
my_object = MyModel.objects.get(pk=1)
except MyModel.DoesNotExist:
raise Http404("No MyModel matches the given query.")
get_object_or_404()の詳細については、djangoオンラインドキュメントをご覧ください。
django 1.7以降では、次のようにできます。
class MyQuerySet(models.QuerySet):
def get_or_none(self, **kwargs):
try:
return self.get(**kwargs)
except self.model.DoesNotExist:
return None
class MyBaseModel(models.Model):
objects = MyQuerySet.as_manager()
class MyModel(MyBaseModel):
...
class AnotherMyModel(MyBaseModel):
...
「MyQuerySet.as_manager()」の利点は、次の両方が機能することです。
MyModel.objects.filter(...).get_or_none()
MyModel.objects.get_or_none()
ここでは、必要に応じて渡すことを可能にするヘルパー関数のバリエーションだQuerySet
インスタンスは、モデルの以外のクエリセットから一意のオブジェクト(存在する場合)を取得したい場合には、all
例えばAに属する子アイテムのサブセットからのオブジェクトのクエリセットを(親インスタンス):
def get_unique_or_none(model, queryset=None, **kwargs):
"""
Performs the query on the specified `queryset`
(defaulting to the `all` queryset of the `model`'s default manager)
and returns the unique object matching the given
keyword arguments. Returns `None` if no match is found.
Throws a `model.MultipleObjectsReturned` exception
if more than one match is found.
"""
if queryset is None:
queryset = model.objects.all()
try:
return queryset.get(**kwargs)
except model.DoesNotExist:
return None
これは次の2つの方法で使用できます。
obj = get_unique_or_none(Model, **kwargs)
以前に議論したようにobj = get_unique_or_none(Model, parent.children, **kwargs)
例外なく:
if SomeModel.objects.filter(foo='bar').exists():
x = SomeModel.objects.get(foo='bar')
else:
x = None
例外を使用する:
try:
x = SomeModel.objects.get(foo='bar')
except SomeModel.DoesNotExist:
x = None
Pythonでいつ例外を使用する必要があるかについては、少し議論があります。一方で、「許可よりも許しを求める方が簡単です」。私はこれに同意しますが、例外はそのままにしておくべきだと思います。例外と「理想的なケース」は、例外を打つことなく実行されるべきです。
という名前のモデルにアタッチされているDjango組み込み例外を使用できます.DoesNotExist
。したがって、ObjectDoesNotExist
例外をインポートする必要はありません。
代わりに:
from django.core.exceptions import ObjectDoesNotExist
try:
content = Content.objects.get(name="baby")
except ObjectDoesNotExist:
content = None
できるよ:
try:
content = Content.objects.get(name="baby")
except Content.DoesNotExist:
content = None
これは、メソッドがNoneを返すことを除いて、Djangoのget_object_or_404からの模倣品です。これは、only()
クエリを使用して特定のフィールドのみを取得する必要がある場合に非常に役立ちます。このメソッドは、モデルまたはクエリセットを受け入れることができます。
from django.shortcuts import _get_queryset
def get_object_or_none(klass, *args, **kwargs):
"""
Use get() to return an object, or return None if object
does not exist.
klass may be a Model, Manager, or QuerySet object. All other passed
arguments and keyword arguments are used in the get() query.
Like with QuerySet.get(), MultipleObjectsReturned is raised if more than
one object is found.
"""
queryset = _get_queryset(klass)
if not hasattr(queryset, 'get'):
klass__name = klass.__name__ if isinstance(klass, type) else klass.__class__.__name__
raise ValueError(
"First argument to get_object_or_none() must be a Model, Manager, "
"or QuerySet, not '%s'." % klass__name
)
try:
return queryset.get(*args, **kwargs)
except queryset.model.DoesNotExist:
return None