Возврат None вместо 'DoesNotExist' в Django: способы обхода
Пройдите тест, узнайте какой профессии подходите
Быстрый ответ
Если вам необходимо получить некий объект из базы данных Django или получить None
в случае, если объект отсутствует, воспользуйтесь следующим подходом:
instance = MyModel.objects.filter(pk=some_id).first()
В данном примере instance
будет или экземпляром класса MyModel (если таковой находится в базе данных), или None
(если такого объекта нет).
Мы советуем познакомиться с немного более изощренными подходами к решению данной задачи. Смотрите ниже.
Назад к базовому: Пользовательский менеджер запросов для безопасного получения объекта
Основы метода safe_get
Создание собственного менеджера запросов с использованием метода safe_get
позволяет изящно обработать ситуации, когда искомый объект отсутствует в базе данных. Метод safe_get
выполняет get-запрос в блоке try...except
и возвращает None
, тем самым предотвращает возникновение исключения.
from django.core.exceptions import ObjectDoesNotExist
class SafeGetManager(models.Manager):
def safe_get(self, **kwargs):
try:
return self.get(**kwargs)
except self.model.DoesNotExist:
return None
class MyModel(models.Model):
objects = SafeGetManager()
Использование метода first()
Метод first()
, появившийся в Django начиная с версии 1.6, стал прекрасным инструментом ORM. Он возвращает первый найденный объект либо None
, предотвращая тем самым возникновение исключений.
instance = MyModel.objects.filter(name="value").first()
# Получим экземпляр MyModel или None
За пределами базового: распространенные сценарии
Когда объект пропустил встречу
Если вы не можете найти объект, используйте safe_get
или .first()
, чтобы получить None
вместо того, чтобы перехватичвать исключение DoesNotExist
вручную.
Обрабатываем исключения как профи
Если нужно точное контролирование процесса обращения к несуществующему объекту, применяйте блок try-except
с SomeModel.DoesNotExist
.
try:
instance = MyModel.objects.get(pk=some_id)
except MyModel.DoesNotExist:
instance = None
Экономим ресурсы с помощью метода exists()
Используйте exists()
для проверки наличия объекта без загрузки всего его содержимого.
if MyModel.objects.filter(pk=some_id).exists():
# Объект найден, можно радоваться
else:
# К сожалению, объект не найден
Обзор с высоты птичьего полета: Визуализация
Представьте, что вы летите над библиотекой, взирая на ряды книжных полок:
Полки Библиотеки:
- Программирование на Python 📗
- Разработка на Django 📘? <--- Вы здесь!
- Веб-дизайн 📙
Вы пытаетесь найти нужную книгу:
book = library.get('Программирование на Python 📗', None)
И, независимо от того, нашли ли вы книгу или нет, продолжаете свой полет:
Результат:
- Найдено: 📘 (Замечательно!)
- Не найдено: None (Не беда...)
Вот так визуализируется работа метода .get()
в Django.
Торжественное завершение: широкая обработка исключений
Захватываем все с помощью ObjectDoesNotExist
Чтобы перехватить исключения об отсутствии объектов любых моделей, используйте ObjectDoesNotExist
.
from django.core.exceptions import ObjectDoesNotExist
try:
instance = MyModel.objects.get(pk=some_id)
except ObjectDoesNotExist:
instance = None
Использование ObjectDoesNotExist
делает ваш код более универсальным.
Оптимизируем код с помощью пользовательских менеджеров и метода .first()
Путем внедрения логики метода get
в пользовательский менеджер вы следуете принципу DRY (Don't Repeat Yourself – не повторяйте себя). Использование метода first()
также способствует поддержанию чистоты кода и его читаемости.