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 a post_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?
data_to_be_updated = {
	"id": 1,
	"title": "this is new title",
	"details" "updated details"
}

blog = models.Blog.objects.get(id=data_to_be_updated['id'])
blog.title = data_to_be_updated['title']
blog.details = data_to_be_updated['details']
blog.save()
Non pythonic way
  • setattr comes to rescue. If you are a newbie then you might not wondering what this does, if this is some special django queryset? No setattr is a python keyword which sets 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 of setattr to have a better pythonic version of the code.
data_to_be_updated = {
	"id": 1,
	"title": "this is new title",
	"details" "updated details"
}

blog = models.Blog.objects.get(id=data_to_be_updated['id'])

for key, value in data_to_be_updated.iteritems():
    setattr(blog, key, value)
blog.save()
Pythonic way

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.