How to "bulk upgrade" using Django?

I want to update a Django table - something like this in raw SQL:

update tbl_name set name = 'foo' where name = 'bar' 

My first result is something like this - but it's nasty, isn't it?

 list = ModelClass.objects.filter(name = 'bar') for obj in list: obj.name = 'foo' obj.save() 

Is there a more elegant way?

+122
django django-models
Sep 30 '12 at 12:30
source share
5 answers

Django 2.2 UPD version now has bulk_date .

See the next section of django documentation

Updating multiple objects at once

In short, you should be able to use:

 ModelClass.objects.filter(name='bar').update(name="foo") 

You can also use F objects for things like string expansion:

 from django.db.models import F Entry.objects.all().update(n_pingbacks=F('n_pingbacks') + 1) 

See Documentation: https://docs.djangoproject.com/en/1.9/topics/db/queries/.

However, note that:

  • This will not use the ModelClass.save method (therefore, if you have some logic inside, it will not run).
  • Django signals will not be emitted.
+205
30 sept
source share
— -

Consider using django-bulk-update found here on GitHub .

Install: pip install django-bulk-update

Implementation: (code obtained directly from the ReadMe file of projects)

 from bulk_update.helper import bulk_update random_names = ['Walter', 'The Dude', 'Donny', 'Jesus'] people = Person.objects.all() for person in people: r = random.randrange(4) person.name = random_names[r] bulk_update(people) # updates all columns using the default db 

Update: As Mark notes, comments are not suitable for updating several thousand lines at once. Although it is suitable for small batches from 10 to 100. The packet size that suits you depends on your processor and query complexity. This tool is more like a wheel body than a dump truck.

+29
Feb 16 '15 at 22:42
source share

Django 2.2 now has a bulk_update method ( release notes ).

https://docs.djangoproject.com/en/dev/ref/models/querysets/#bulk-update

Example:

 # get a pk: record dictionary of existing records updates = YourModel.objects.filter(...).in_bulk() .... # do something with the updates dict .... if hasattr(YourModel.objects, 'bulk_update') and updates: # Use the new method YourModel.objects.bulk_update(updates.values(), [list the fields to update], batch_size=100) else: # The old & slow way with transaction.atomic(): for obj in updates.values(): obj.save(update_fields=[list the fields to update]) 
+6
Jan 04 '19 at 8:28
source share

If you want to set the same value in a row collection , you can use the update () method in conjunction with any query term to update all rows in a single query:

 some_list = ModelClass.objects.filter(some condition).values('id') ModelClass.objects.filter(pk__in=some_list).update(foo=bar) 

If you want to update a collection of strings with different values depending on some conditions, you can at best package updates according to the values. Suppose you have 1000 rows in which you want to set one of the X values ​​for a column, then you can prepare packages in advance, and then only execute X update requests (each essentially has the form of the first example above) + initial SELECT -query .

If each row requires a unique value, there is no way to avoid a single update request. Perhaps look at other architectures, such as CQRS / Event Sourcing, if you need performance in this latter case.

+2
Nov 15 '18 at 14:05
source share
 how to update all value of any user getting user id match=Insert.objects.get(uid=id) if request.method=="POST": firstName=request.POST.get('FirstName') lastName=request.POST.get('LastName') Phone=request.POST.get('Phone') Address=request.POST.get('Address') UserName=request.POST.get('UserName') Password=request.POST.get('Password') Email=request.POST.get('Email') Insert.objects.filter(uid=id).update(firstName='hello') return redirect(request,'perform/alldata.html') 
0
Jun 27 '19 at 8:14
source share



All Articles