Ответ
Распространенные ошибки и антипаттерны в Django ORM часто приводят к неэффективному коду, багам и проблемам с производительностью.
-
Проблема N+1 запросов
- Ошибка: Получение связанных объектов в цикле без использования
select_relatedилиprefetch_related. - Последствие: Резкое увеличение количества запросов к БД и деградация производительности.
# Антипаттерн: N+1 запросов for book in Book.objects.all(): print(book.author.name) # Новый запрос для каждого автора # Правильно: 1 запрос for book in Book.objects.select_related('author'): print(book.author.name) - Ошибка: Получение связанных объектов в цикле без использования
-
Использование
len(queryset)вместо.count()- Ошибка: Подсчет количества объектов путем загрузки всего QuerySet в память.
- Последствие: Избыточное потребление памяти и медленная работа на больших таблицах. Правильно использовать
queryset.count(), который транслируется в эффективныйSELECT COUNT(*).
-
Создание объектов в цикле вместо
bulk_create()- Ошибка: Вызов
Model.objects.create()илиmodel.save()внутри цикла. - Последствие: Один
INSERTзапрос на каждую итерацию.bulk_create()объединяет все операции в один запрос.
- Ошибка: Вызов
-
Использование
filter()вместоget()для уникального объекта- Ошибка: Искать один объект через
MyModel.objects.filter(pk=1), что возвращает QuerySet. - Последствие: Требуется дополнительная обработка результата (
.first(),[0]). Методget()предназначен именно для этого: он возвращает объект или вызывает исключение (DoesNotExistилиMultipleObjectsReturned), что делает код более строгим и предсказуемым.
- Ошибка: Искать один объект через
-
Отсутствие атомарных транзакций
- Ошибка: Выполнение нескольких операций записи (создание, обновление, удаление), которые должны быть единым целым, без обертывания в
transaction.atomic(). - Последствие: Риск нарушения целостности данных, если одна из операций завершится с ошибкой.
- Ошибка: Выполнение нескольких операций записи (создание, обновление, удаление), которые должны быть единым целым, без обертывания в
-
Путаница между
null=Trueиblank=True- Ошибка: Неправильное использование этих атрибутов поля.
- Последствие:
null=Trueразрешает хранитьNULLв базе данных (для полей, не являющихся текстовыми).blank=Trueотносится к валидации форм Django и разрешает оставлять поле пустым. Неправильное использование может привести к ошибкам на уровне БД или валидации.
Ответ 18+ 🔞
А, слушай, смотри, вот эти ваши распиздяйства с Django ORM, блядь. Сидят люди, пишут код, а потом охуевают, почему всё тормозит и падает. Ёпта, давайте по полочкам, как не надо делать, чтобы потом не плакать.
Ну первое, классика жанра, ебать мои старые костыли — проблема N+1 запросов. Представь: ты получаешь список книг, а потом для каждой книги в цикле лезешь за автором. И что? А то, что на каждую книгу — новый запрос в базу! Это же пиздец, а не производительность.
# Делать так — это идти нахуй с такими подходами
for book in Book.objects.all():
print(book.author.name) # Новый запрос на каждую итерацию, ёбта!
# А делать надо вот так, умный человек
for book in Book.objects.select_related('author'):
print(book.author.name) # Всё за один раз, одним махом, красота!
Дальше, второй номер нашего позорного хит-парада. Использование len(queryset) вместо .count(). Ну ты чего, совсем, блядь? Ты что, хочешь загрузить в память все сто тысяч записей, чтобы просто посчитать, сколько их? Да ты гений, просто хуй с горы! Используй .count(), он сделает один красивый SELECT COUNT(*) и не будет ебать мозги твоему серверу.
Третий пункт — создание объектов в цикле. О, это моя любимая, блядь. Люди делают Model.objects.create() внутри for. И что? Каждый create — это отдельный запрос INSERT. База данных просто обоссытся от счастья, когда их будет тысяча. А ты возьми да примени bulk_create() — один запрос, все объекты разом, как по маслу. Элементарно, Ватсон, ёпта!
Четвёртое. Фильтровать там, где нужно получить один объект. Зачем, сука, писать MyModel.objects.filter(pk=1), если есть .get()? Ты что, QuerySet коллекционируешь? .get() тебе сразу объект выдаст, а если что-то не так — исключение бросит. Чётко, ясно, без лишних телодвижений. Не выёбывайся.
Пятое — отсутствие атомарных транзакций. Это когда у тебя несколько операций должны быть как единое целое, а ты их просто подряд пишешь. А потом одна сломалась, а остальные уже выполнились — и пошла пизда целостности данных. Оберни это всё в transaction.atomic(), и спи спокойно. Либо всё выполнится, либо откатится, как будто ничего и не было. Волшебство, блядь!
И шестое, для особо одарённых. Путаница между null=True и blank=True. Ну это вообще, в рот меня чих-пых! null=True — это про базу данных, можно хранить NULL. blank=True — это про формы Django, можно поле оставить пустым. Перепутаешь — получишь ошибки на ровном месте, и будешь потом чесать репу, почему всё не работает. Запомни раз и навсегда, ёпта!
Вот так вот, дружок. Не наступай на эти грабли, а то будет больно и стыдно.