Метод bulk_update

Метод bulk_update применяется к QuerySet и выполняет массовое обновление указанных полей для всех объектов, содержащихся в QuerySet. В отличие от метода update, который обновляет все записи одинаково, bulk_update позволяет задать уникальные значения для каждой записи. Метод принимает список объектов модели и список полей, которые необходимо обновить, и выполняет один SQL-запрос для всех обновлений. Это делает его идеальным для пакетной обработки данных, когда требуется изменить разные значения у разных записей.

Синтаксис

pythonModel.objects.bulk_update(objs, fields, batch_size=None)

Параметры метода:

pythonobjs    - список объектов модели, которые нужно обновить
fields    - список полей модели, которые будут обновлены
batch_size  - опционально, размер партии для массового обновления

Пример . С обновлением нескольких записей

Давайте обновим статусы у нескольких статей массово:

pythonfrom 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)

Результат выполнения кода:

python"5"

Пример . С использованием batch_size

Для больших объемов данных используем параметр batch_size для разбиения на партии:

pythonfrom 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)

Результат выполнения кода:

python"150"

Пример . С обновлением связанных полей

Обновим несколько полей у статей, включая связанное поле и поле с датой:

pythonfrom 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)

Результат выполнения кода:

python"10"

Важные особенности использования

Метод bulk_update не вызывает сигналы pre_save и post_save для каждой записи, что делает его более производительным, но может нарушить бизнес-логику. Также метод не обновляет поле auto_now для полей с DateTimeField, поэтому их нужно включать в список fields для явного обновления.

Сравнение с методом update

В отличие от update, который выполняет одно и то же изменение для всех записей, bulk_update позволяет задавать индивидуальные значения для каждой записи:

pythonfrom 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)

Результат выполнения кода:

python"1"

Смотрите также

  • метод bulk_create,
    который выполняет массовое создание записей в базе данных
  • метод update,
    который выполняет массовое обновление полей с одинаковым значением
  • метод get_or_create,
    который создает или получает запись из базы данных
  • метод update_or_create,
    который обновляет или создает запись в базе данных