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

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

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

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

Ответы [ 15 ]

270 голосов
/ 22 июня 2010

Нет встроенного способа сделать это.Django будет вызывать исключение DoesNotExist каждый раз.Идиоматический способ справиться с этим в python - это обернуть его в попытку try:

try:
    go = SomeModel.objects.get(foo='bar')
except SomeModel.DoesNotExist:
    go = None

Что я сделал, так это подкласс модели.менеджер по моим моделям.Таким образом, вы можете написать: SomeModel.objects.safe_get(foo='bar').

133 голосов
/ 05 апреля 2015

Начиная с django 1.6, вы можете использовать метод first () следующим образом:

Content.objects.filter(name="baby").first()
29 голосов
/ 22 июня 2010

Из документов Django

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
27 голосов
/ 19 декабря 2013

Для этого вы можете создать универсальную функцию.

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.

Примечание. Возникает исключение MultipleObjectsReturned, если для name = "baby" возвращено более одной записи

12 голосов
/ 20 августа 2016

Вы можете сделать это следующим образом:

go  = Content.objects.filter(name="baby").first()

Теперь переменная go может быть либо нужным вам объектом, либо None

Ref: https://docs.djangoproject.com/en/1.8/ref/models/querysets/#django.db.models.query.QuerySet.first

12 голосов
/ 22 июля 2014

Чтобы упростить задачу, вот фрагмент кода, который я написал, на основе входных данных из замечательных ответов здесь:

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 ()

11 голосов
/ 23 июля 2014

вы можете использовать exists с фильтром:

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

просто альтернатива, если вы хотите знать, существует ли она

7 голосов
/ 20 января 2016

Это одна из тех раздражающих функций , которые вы, возможно, не захотите повторно реализовывать:

from annoying.functions import get_object_or_None
#...
user = get_object_or_None(Content, name="baby")
7 голосов
/ 21 апреля 2014

Обработка исключений в разных точках в ваших представлениях может быть очень трудоемкой. А как насчет определения собственного менеджера моделей в файле models.py, например

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
3 голосов
/ 28 сентября 2016

Если вы хотите простое однострочное решение, которое не включает обработку исключений, условные операторы или требование Django 1.6+, сделайте это вместо:

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