web-dev-qa-db-ja.com

オブジェクトが存在する場合はどのように取得しますか、存在しない場合はNoneを取得しますか?

モデルマネージャーにオブジェクトを取得するように依頼すると、一致するオブジェクトがないときにDoesNotExistが発生します。

go = Content.objects.get(name="baby")

DoesNotExistの代わりに、どのようにgoNoneにできますか?

168
TIMEX

これを行うための「組み込み」の方法はありません。 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')と書くことができます。

264
Arthur Debert

Django 1.6以降では、 first() メソッドを次のように使用できます。

Content.objects.filter(name="baby").first()
130
FeroxTL

Django docsから

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
29
Amarghosh

このための汎用関数を作成できます。

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が発生します。

26
Ranju R

次の方法で実行できます。

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

12
Gaurav

物事を簡単にするために、ここに素晴らしい返信からの入力に基づいて、私が書いたコードのスニペットがあります:

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()ができました。

12
Moti Radomski

フィルターでexistsを使用できます。

Content.objects.filter(name="baby").exists()
#returns False or True depending on if there is anything in the QS

存在するかどうかだけを知りたい場合の代替手段

11
Ryan Saxe

迷惑な関数 の1つで、再実装したくない場合があります。

from annoying.functions import get_object_or_None
#...
user = get_object_or_None(Content, name="baby")
7
mknecht

ビューのさまざまなポイントで例外を処理するのは非常に面倒な場合があります。

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
7
Adil Malik

例外処理、条件ステートメント、またはDjango 1.6+の要件を含まないシンプルな1行のソリューションが必要な場合は、代わりにこれを実行します。

x = next(iter(SomeModel.objects.filter(foo='bar')), None)
3
blhsing

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.")

Djangoオンラインドキュメントでget_object_or_404()の詳細を読むことができます。

2
Mohammad Reza

.DoesNotExistという名前のモデルに添付されたDjango組み込み例外を使用できます。したがって、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
1
zakiakhmad

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インスタンスを渡すことができるヘルパー関数のバリエーションがあります親インスタンスへ):

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つの方法で使用できます。

  1. obj = get_unique_or_none(Model, **kwargs)前に説明したように
  2. obj = get_unique_or_none(Model, parent.children, **kwargs)
1
Gary

例外なく:

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で例外を使用するタイミングについては、少し議論があります。一方では、「許可よりも許しを求める方が簡単です」。私はこれに同意しますが、例外はそのまま残り、「理想的なケース」はヒットせずに実行されるべきだと思います。

1