Search code examples
pythondjangosavedjango-queryset

Best way to bulk update query with dynamic values conditionally in Django


I am just wondering if it's possible to bulk save queries in django.

for example, usually I would have to loop through each object

for obj in queryset:
    if condition:
        obj.field = True
        obj.save()

EDIT:

I know the above case can be handled with the update method. However, the sample above is saving all the fields with the same value. What if there are different conditions?

for obj in queryset:
    if condition:
        obj.field = True
        obj.save()
    else:
        obj.field = False
        obj.save()

The above might not be the best sample I can think of at the moment but something similar I would say.

would there be a faster way to do this?

Thanks in advance for any advices


Solution

  • Querysets have an update method that does precisely this. There are some caveats, however, like model save methods not being called. Keep that in mind if you override and implement your own save methods for your models.

    From the django docs:

    For example, to turn comments off for all blog entries published in 2010, you could do this:

    >>> Entry.objects.filter(pub_date__year=2010).update(comments_on=False)
    

    So, in other words queryset.update(field='value')

    UPDATE: concerning doing this dynamically based on conditionals...

    Because update performs at the SQL level (performed by the DB), you would want to work in your condition into your query, which is almost always possible in one way or another. You may do multiple queries to get the effect.

    def my_bulk_update():
        MyModel.objects.filter(conditional_field=True).update(field=True)
        MyModel.objects.filter(conditional_field=False).update(field=False)
    

    There are many clever ways you can make queries to accomplish this, (Including annotating, aggregating , expressions and more)... You may be surprised how much logic you can stuff into a query. Be sure to check out the docs on making queries. And of course, you can always write your own SQL to do effectively the same thing, too, if the ORM doesn't quite cut it with generating the query.

    If the logic is really complex and can't be done with SQL, you can do roughly as you've already written, but may want to use transactions for performance if you have a large number of records.