Метод bulk_update
Метод bulk_update применяется к QuerySet и выполняет
массовое обновление указанных полей для всех объектов,
содержащихся в QuerySet. В отличие от метода update,
который обновляет все записи одинаково, bulk_update
позволяет задать уникальные значения для каждой записи.
Метод принимает список объектов модели и список полей,
которые необходимо обновить, и выполняет один SQL-запрос
для всех обновлений. Это делает его идеальным для
пакетной обработки данных, когда требуется изменить
разные значения у разных записей.
Синтаксис
Model.objects.bulk_update(objs, fields, batch_size=None)
Параметры метода:
objs - список объектов модели, которые нужно обновить
fields - список полей модели, которые будут обновлены
batch_size - опционально, размер партии для массового обновления
Пример . С обновлением нескольких записей
Давайте обновим статусы у нескольких статей массово:
from myapp.models import Article
from datetime import datetime
# Получаем статьи для обновления
articles_to_update = Article.objects.filter(
created_at__year=2025
)[:5]
# Изменяем значения полей в памяти
for article in articles_to_update:
article.status = 'draft'
article.updated_at = datetime.now()
# Массовое обновление
Article.objects.bulk_update(
articles_to_update,
['status', 'updated_at']
)
# Проверяем результат
res = Article.objects.filter(status='draft').count()
print(res)
Результат выполнения кода:
"5"
Пример . С использованием batch_size
Для больших объемов данных используем параметр batch_size
для разбиения на партии:
from myapp.models import Article
# Получаем все статьи
all_articles = Article.objects.all()
# Изменяем значения
for article in all_articles:
article.status = 'published'
# Обновляем партиями по 100 записей
Article.objects.bulk_update(
all_articles,
['status'],
batch_size=100
)
res = Article.objects.filter(status='published').count()
print(res)
Результат выполнения кода:
"150"
Пример . С обновлением связанных полей
Обновим несколько полей у статей, включая связанное поле и поле с датой:
from myapp.models import Article, User
from datetime import datetime
# Получаем пользователя для обновления
author = User.objects.get(username='john')
# Получаем статьи для обновления
articles = Article.objects.filter(
status='draft'
)[:10]
# Изменяем значения
for article in articles:
article.author = author
article.status = 'review'
article.updated_at = datetime.now()
# Массовое обновление
Article.objects.bulk_update(
articles,
['author', 'status', 'updated_at']
)
res = Article.objects.filter(
author=author,
status='review'
).count()
print(res)
Результат выполнения кода:
"10"
Важные особенности использования
Метод bulk_update не вызывает сигналы
pre_save и post_save для каждой
записи, что делает его более производительным,
но может нарушить бизнес-логику. Также метод не
обновляет поле auto_now для полей с
DateTimeField, поэтому их нужно включать
в список fields для явного обновления.
Сравнение с методом update
В отличие от update, который выполняет
одно и то же изменение для всех записей,
bulk_update позволяет задавать
индивидуальные значения для каждой записи:
from myapp.models import Article
# update - одинаковое изменение
Article.objects.filter(
status='draft'
).update(status='published')
# bulk_update - разные изменения
articles = Article.objects.filter(
status='draft'
)[:3]
# Устанавливаем разные статусы
articles[0].status = 'published'
articles[1].status = 'review'
articles[2].status = 'archived'
Article.objects.bulk_update(
articles,
['status']
)
res = Article.objects.filter(status='published').count()
print(res)
Результат выполнения кода:
"1"
Смотрите также
-
метод
bulk_create,
который выполняет массовое создание записей в базе данных -
метод
update,
который выполняет массовое обновление полей с одинаковым значением -
метод
get_or_create,
который создает или получает запись из базы данных -
метод
update_or_create,
который обновляет или создает запись в базе данных