Evgenii Legotckoi
15 мая 2018 г. 20:07

Django - Snippet 001. get_object_or_none

Содержание

В шорткатах Django есть функция get_object_or_404 , но при этом нет функции get_object_or_none , которая может быть полезна в том случае, когда мы не хотим вызывать сразу ошибку 404, но при этом нам необходимо выполнить какие либо действия в том случае, если объект не существует в базе данных.

Удалось найти обсуждение в интернете, где разработчики отписались, что подобный функционал может быть легко внедрён в качесте until функции в рамках проекта разработчика и внедрять его в основной код не требуется.


Подобный функционал мне понадобился для поиска тегов на сайте.

Поэтому я его добавил в ядро сайта в качестве шортката.

shortcuts.py

  1. # -*- coding: utf-8 -*-
  2.  
  3.  
  4. def get_object_or_none(klass, *args, **kwargs):
  5. try:
  6. return klass._default_manager.get(*args, **kwargs)
  7. except klass.DoesNotExist:
  8. return None

Пример

  1. def get_queryset(self, **kwargs):
  2. q = self.request.GET.get('q')
  3. tag = get_object_or_none(Tag, name=q)
  4. if tag:
  5. return TaggedItem.objects.all().filter(tag=tag)
  6. return []

Вам это нравится? Поделитесь в социальных сетях!

ПК
  • 19 мая 2018 г. 17:11
Тоже искал подобную функцию, чтобы не обрабатывать каждый раз исключения. И нашёл на so совет использовать вместо неё метод менеджера first(), который возвращает None при пустом queryset. Т.е можно было так
tag = Tag.objects.first()
if tag:
  return tag
return []
Evgenii Legotckoi
  • 19 мая 2018 г. 18:25

В вашем случае происходит подмена сущностей. Вместо того, чтобы взять один конкретный объект, вы забираете queryset а потом берёте из него первый объект. Нехорошо будет, если queryset в каком-то случае вернёт два объекта или более. Проблема в том, что вы не узнаете об этой ошибке никак, а это нарушит логику работы приложения с последствиями в будущем. Мой вариант решения хотя бы порушит приложение и даст знать что существует два одинаковых по каким-то параметрам объекта, и нужно будет принимать меры для исправления.

Лично мне не нравится ваше решение.
ПК
  • 19 мая 2018 г. 18:34

Согласен с тем что ваше решение более очевидно при чтении кода. first() же здесь применяется не совсем по назначению. А с последствиями "моего" решения не согласен. Метод вернёт только один объект, если он существует, или None. А целостность базы данных лучше, наверно, проверять на этапе добавления записи, а не при доступе к ней. В остальном поведение идентично вашему методу.

Evgenii Legotckoi
  • 19 мая 2018 г. 18:44

А вы гарантируете, что метод first вернёт нужный объект, если в таблице две похожих записи? Этого никто не гарантирует. Может возникнуть неопределённое поведение приложения, если запись не так, что требовалась. А насчёт целостности базы данных перед добавлением я согласен, хотя по идее уровни блокировки на чтение записи в самой базе данных должны разруливать такую ситуацию, но у меня случалась подобная ситуация. Увы..

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
  • Последние комментарии
  • Evgenii Legotckoi
    16 апреля 2025 г. 17:08
    Благодарю за отзыв. И вам желаю всяческих успехов!
  • IscanderChe
    12 апреля 2025 г. 17:12
    Добрый день. Спасибо Вам за этот проект и отдельно за ответы на форуме, которые мне очень помогли в некоммерческих пет-проектах. Профессиональным программистом я так и не стал, но узнал мно…
  • AK
    1 апреля 2025 г. 11:41
    Добрый день. В данный момент работаю над проектом, где необходимо выводить звук из программы в определенное аудиоустройство (колонки, наушники, виртуальный кабель и т.д). Пишу на Qt5.12.12 поско…
  • Evgenii Legotckoi
    9 марта 2025 г. 21:02
    К сожалению, я этого подсказать не могу, поскольку у меня нет необходимости в обходе блокировок и т.д. Поэтому я и не задавался решением этой проблемы. Ну выглядит так, что вам действитель…
  • VP
    9 марта 2025 г. 16:14
    Здравствуйте! Я устанавливал Qt6 из исходников а также Qt Creator по отдельности. Все компоненты, связанные с разработкой для Android, установлены. Кроме одного... Когда пытаюсь скомпилиров…