1

I try to modify many instance of some model (like User model), and this changes is different (I don't want to use update QuerySet method and not works for my scenario).

For example some user need to change first_name and some user need to change last_name and get users like : all_user = User.objects.all()

I think if I use save method for each instance after change, Django sent one query for save that!

How can I save all changes to database in one query instead of use foreach on models and save that one by one?

markwalker_
  • 12,078
  • 7
  • 62
  • 99
A.Motahari
  • 173
  • 5
  • 10
  • 2
    Does this answer your question? [How to 'bulk update' with Django?](https://stackoverflow.com/questions/12661253/how-to-bulk-update-with-django) – iklinac Jan 25 '21 at 00:05

1 Answers1

3

Given the comment from @iklinac, I would thoroughly recommend implementing django's own approach to bulk updates detailed here

It's quite similar to my original answer, below, but it looks like the functionality is now built in.

# bulk_update(objs, fields, batch_size=None)
>>> objs = [
...    Entry.objects.create(headline='Entry 1'),
...    Entry.objects.create(headline='Entry 2'),
... ]
>>> objs[0].headline = 'This is entry 1'
>>> objs[1].headline = 'This is entry 2'
>>> Entry.objects.bulk_update(objs, ['headline'])

Original answer

There's a package called django-bulk-update which is similar to bulk create which is builtin to django.

An example of where I use this, is part of an action in an admin class;

@admin.register(Token)
class TokenAdmin(admin.ModelAdmin):
    list_display = (
        'id',
        'type'
    )

    actions = (
        'set_type_charity',
    )

    def set_type_charity(self, request, queryset):
        for token in queryset:
            token.type = Token.Type.CHARITY

        bulk_update(
            queryset,
            update_fields=['type', 'modified'],
            batch_size=1000
        )

Usage, taken from their readme;

With manager:

import random
from django_bulk_update.manager import BulkUpdateManager
from tests.models import Person

class Person(models.Model):
    ...
    objects = BulkUpdateManager()

random_names = ['Walter', 'The Dude', 'Donny', 'Jesus']
people = Person.objects.all()
for person in people:
  person.name = random.choice(random_names)

Person.objects.bulk_update(people, update_fields=['name'])  # updates only name column
Person.objects.bulk_update(people, exclude_fields=['username'])  # updates all columns except username
Person.objects.bulk_update(people)  # updates all columns
Person.objects.bulk_update(people, batch_size=50000)  # updates all columns by 50000 sized chunks

With helper:

import random
from django_bulk_update.helper import bulk_update
from tests.models import Person

random_names = ['Walter', 'The Dude', 'Donny', 'Jesus']
people = Person.objects.all()
for person in people:
  person.name = random.choice(random_names)

bulk_update(people, update_fields=['name'])  # updates only name column
bulk_update(people, exclude_fields=['username'])  # updates all columns except username
bulk_update(people, using='someotherdb')  # updates all columns using the given db
bulk_update(people)  # updates all columns using the default db
bulk_update(people, batch_size=50000)  # updates all columns by 50000 sized chunks using the default db
markwalker_
  • 12,078
  • 7
  • 62
  • 99