How to update multiple fields in Django model efficiently?
The TLDR answer:
The first answer which you would get when you search django model update
on google you would find the .update()
Django ORM. While this is great, let us see few points about .update()
queryset -
post_save
,pre_save
signals does not get triggered. While this might not be important for most of the users, but I have burnt my hand multiple times when I had apost_save
signal configured to do few tasks on model data changes. And all of a sudden my code started to behave erratic.- When to use
.update()
- If you want to updated something which doesn't have signal defined. - Performance oriented, since
update
query would be using a single db query, while select and update does a round trip. - Bulk update operation for entries
What are the alternatives you have if you want to use update
which would also trigger all the built-in model signals.
- Good old way. You can do a
filter/get
query and then manually update the fields using a loop or single update. But that is no fun, you didn't read the blog all the way till here so that I suggest you this right?
setattr
comes to rescue. If you are a newbie then you might not wondering what this does, if this is some special django queryset? Nosetattr
is a python keyword whichsets the value of the attribute of an object.
Whenever we want to update some model, we are dealing with python object so we can make use ofsetattr
to have a better pythonic version of the code.
Advantage of using the above method:
- Cleaner approach which is expandable. Lets say you have 10 different fields you don't have to worry have updating the fields manually
- All built-in model signals would be working as expected.
Caveats:
- Any new developer might not be able to read it at once, unless reads through what
setattr
does in python. - We are making 2 db calls, first one to get the data, second one to save the data.