Evgenii Legotckoi
15 травня 2018 р. 20:07

Django – фрагмент 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 вернёт нужный объект, если в таблице две похожих записи? Этого никто не гарантирует. Может возникнуть неопределённое поведение приложения, если запись не так, что требовалась. А насчёт целостности базы данных перед добавлением я согласен, хотя по идее уровни блокировки на чтение записи в самой базе данных должны разруливать такую ситуацию, но у меня случалась подобная ситуация. Увы..

Коментарі

Only authorized users can post comments.
Please, Log in or Sign up
  • Останні коментарі
  • Evgenii Legotckoi
    16 квітня 2025 р. 17:08
    Благодарю за отзыв. И вам желаю всяческих успехов!
  • IscanderChe
    12 квітня 2025 р. 17:12
    Добрый день. Спасибо Вам за этот проект и отдельно за ответы на форуме, которые мне очень помогли в некоммерческих пет-проектах. Профессиональным программистом я так и не стал, но узнал мно…
  • AK
    01 квітня 2025 р. 11:41
    Добрый день. В данный момент работаю над проектом, где необходимо выводить звук из программы в определенное аудиоустройство (колонки, наушники, виртуальный кабель и т.д). Пишу на Qt5.12.12 поско…
  • Evgenii Legotckoi
    09 березня 2025 р. 21:02
    К сожалению, я этого подсказать не могу, поскольку у меня нет необходимости в обходе блокировок и т.д. Поэтому я и не задавался решением этой проблемы. Ну выглядит так, что вам действитель…
  • VP
    09 березня 2025 р. 16:14
    Здравствуйте! Я устанавливал Qt6 из исходников а также Qt Creator по отдельности. Все компоненты, связанные с разработкой для Android, установлены. Кроме одного... Когда пытаюсь скомпилиров…