Как получить объект, если он существует, или None, если он не существует? - PullRequest
170 голосов
/ 22 июня 2010

Когда я прошу менеджера модели получить объект, он вызывает DoesNotExist, когда нет подходящего объекта.

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

Вместо DoesNotExist, как я могу иметь go вместо None?

Ответы [ 15 ]

2 голосов
/ 06 июня 2017

Я думаю, что неплохо использовать 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.

1 голос
/ 26 мая 2016

Мы можем использовать встроенное исключение 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
1 голос
/ 20 января 2016

Начиная с версии 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()
1 голос
/ 28 апреля 2015

Без исключения:

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 голос
/ 30 июля 2014

Вот вариант вспомогательной функции, который позволяет вам при желании передать экземпляр 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

Это может использоваться двумя способами, например:

  1. obj = get_unique_or_none(Model, **kwargs), как обсуждалось ранее
  2. obj = get_unique_or_none(Model, parent.children, **kwargs)
...