Перенесите уменьшение в один UPDATE через F и Decimal. Но заранее определите округление и учтите, что QuerySet.update не вызывает save и сигналы.
Массовая корректировка цен для всех продуктов
Перенесите уменьшение в один UPDATE через F и Decimal. Но заранее определите округление и учтите, что QuerySet.update не вызывает save и сигналы.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Необходимо проверить, правильно ли реализована логика изменения стоимости каждого товара в базе данных: цена снижается на 5 %, после чего вызывается метод save() для каждой записи. Оцените, возможно ли реализовать данную операцию более эффективно.
products = Product.objects.all()
for product in products:
product.price *= 0.95
product.save()
Ответ
Перенесите уменьшение в один UPDATE через F и Decimal. Но заранее определите округление и учтите, что QuerySet.update не вызывает save и сигналы.
from decimal import Decimal
from django.db.models import F
Product.objects.update(price=F('price') * Decimal('0.95'))
Для DecimalField множитель float из исходника может вызвать ошибку смешения типов; для денежных сумм нужен точный десятичный коэффициент. Итоговое округление зависит от типа столбца и СУБД — закрепите правило до массового изменения.
F вычисляет от актуальной цены в БД и не загружает все объекты в Python. Если важны переопределённый save, сигналы или сложные расчёты, потребуется другой путь. Повторный запуск снова снизит цены: для разовой акции нужен учёт её применения и резервная копия/снимок исходных значений.