Comments 31
Я уже в статье отметил, что считаю, что в этой функции ошибка. Ошибка в логике: функция должна получать только один объект, если он есть. Не два, не 25, и не два миллиона. Жаль только, что мой манкипатчинг (смешное слово) не исправляет эту ошибку а только уменьшает количество получаемых объектов.
В реальной Django это невозможно сделать за один запрос. Потому текущая логика метода такова:
- Проинициализировать объекты данными из запроса, будет проинициализировано столько объектов, сколько возвращено строк,
- Объекты сохраняются в "_result_cache".
- Если обьект один — Get вернет ссылку на первый и единственный объект в "_result_cache"
- GET выдаст ошибку «DoesNotExist» если _result_cache пустой
- GET вернет MultipleObjectsReturned, при этом "_result_cache" будет заполнен несколькими объектами и их количество не учитывается.
В Django 3 появилось ограничение в 25 строк, это значит, что в sql запроса есть «LIMIT». Во всех предыдущих версиях этого ограничения не было вообще, и мы поставили у себя в проекте ограничение на количество возвращенных строк до 2х.
В этом случае будут проинициированы максимум два обьекта. После чего Get выдаст ошибки, если получен иной результат, чем один объект.
Ограничение на 2 объекта вместо 25 я предлагаю и для новой Django.
то что лимит в джанге добавили — это хорошо. но между 2 и 25 разницы особой нет, а вот миллионы да, могут стрельнуть
прошу указать: где в коде или тексте статьи ошибка, подразумевающая, что результатом работы метода GET будет возврат двух и более объектов.
В итоге вы могли получить несколько миллионов объектов в памяти, только для того, чтобы узнать, что найден более, чем 1 объект.
вот же.
возвращает .get() один объект, но ему еще надо рейзить ошибку, когда из базы более 1 объекта прилетело, что свидетельствует об ошибке в логике программы.
Объекты сохраняются в "_result_cache".
Если обьект один — Get вернет ссылку на первый и единственный объект в "_result_cache"
GET выдаст ошибку «DoesNotExist» если _result_cache пустой
GET вернет MultipleObjectsReturned, при этом "_result_cache" будет заполнен несколькими объектами и их количество не учитывается.
_result_cache хранится в памяти, методом GET не возвращается.
однако именно она была приведена с комментарием «вот же», как пример того, что результатом работы метода GET будет возврат более одного объекта.
Эта логическая ошибка в стандартном методе get заключается в том, что на 9 строке метода создаются объекты, которые, если их можно было создать больше одного — создаваться не должны были в принципе. А они создаются, и только потом проверяется их количество.
Кстати, когда выпал MultipleObjectsReturned, на обработке ошибки воспользоваться этими УЖЕ созданными «MultipleObjects» нельзя.
Если бы этого исключения и правда никогда не должно было происходить ("наша цель получить какого-то человека а не ошибку"), то можно было бы просто писать всегда first. Для корректного кода это равноценная замена.
Но если мы пишем get — значит, иногда всё-таки исключение происходить должно. И видеть в этом "иногда" серьёзную деградацию производительности очень не хочется.
Скажите, а в каких случаях, по-вашему, использование get оправдано? Может, его надо вообще удалить из django?
Ясно, с этого вам и надо было начинать, а не требовать объяснить разницу между 25 записями и 2мя когда вы не понимаете зачем вообще сам метод нужен...
Так вот, есть такой принцип — fail fast. Он говорит, что программа, которая обнаружила ошибку в окружении или в самой себе, должна как можно быстрее сообщить об ошибке, чтобы её можно было исправить.
Да, при этом появляется риск что программа поломается уже у пользователя — но он компенсируется тем, что при таком подходе больше багов будет отловлено на этапах отладки и тестирования.
Рассмотрим ваши примеры. Вот у нас оказались два пользователя с ником swelf. Вы бы предпочли узнать об этом при первом же входе на хабр, или когда ваш двойник словит бан, и этот бан прилетит вам? Первое неприятно, но быстро решится через поддержку, а во втором случае ошибка может так и остаться незамеченной.
— не всё.
В коде метода get ошибка логики. Еще нет программы которая использует этот метод, еще нет примера кода, а ошибка уже есть: алгоритм get создает объекты в случае, когда создавать их не должен вообще. по-моему мнению — эта ошибка. Исправить ее в джанго возможности нет. Потому есть рекомендация минимизировать последствия в тех случаях, когда действительно используется get.
50% гениальность / 50% тупость.
К сожалению вся джанга такая. Админка подходит только для стандартных задач, кастомизируется через жуткие костыли. Метод
get
вообще перестали использовать, только first
. Да много чего хотелось бы поменять, поэтому вопрос, не пробовали пропихнуть свои изменения в саму джангу вместо очередной батарейки?Админка подходит только для стандартных задач, кастомизируется через жуткие костыли.
Будь моя воля, я бы вообще запретил использовать админку джанги для чего-то нестандартного. А то накидают костылей, а потом сиди и разгребай все это в попытках обновится на следующую версию.
Так и сидим на 1.5 в одном проекте — фичи нужно завозить, а на перепиливание админки времени нет (там используются неподдерживаемые более модули на JS).
к сожалению, заметил, что развитие Django сильно замедлилось
Хм, в Django 3.0 же добавили поддержку асинхронности, разве это не большой шаг вперед? Я, правда, еще не смотрел как это выглядит, может быть это просто маркетинговый ход и работать с этим невозможно?
Когда у средней руки проекта пявляется минорный патч, он всегда выглядит революционно. Когда проект развился в нечто большое, минорными патчами уже никого не удивишь.
Django 3.0 — начато переписывание полностью синхронной Django под асинхронность. И уже вполне юзаемо, хотя это только начало. Как по мне — неплохо.
Хотелось бы узнать, что такого революционного должно появиться в Django, чтобы автор (или согласные с ним комментирующие) решил, что это — достойное развитие? Только без фраз типа «сделайте нормальную ORM». А то если дойдем до вкусовщины и каждый найдет свой любимый рецепт для решения той или иной задачи.
Возможность инлайнов в середине фиелдсета формы админпанели.
(Правится переопределением change_form)
Возможность переменных фиелдсетов в формсетах (Правится переопределением __iter__ филдсета)
Асинхронные формсеты (в текущей реализации невозможно)
Очень удивит, если появится документация по объекту query
Отказ от жесткой привязки к jquery тоже порадует.
То что менеджер шаблонов сделали асинхронным… как то все равно. Или там еще что-то изменилось?
Я не говорю, что предложенные Вами изменения несущественны. Но посудите сами: неужели инлайны в админке — то, чего ждет все комьюнити? Сделают, может. Будет этакий междудельный фикс минорный. Или сами пулл-реквестик протолкните. Тогда, если когда-нибудь увидимся, — с меня пиво =D.
Нас Django вкус волнует и манит