Codementor Events

Improving Django's Model.save() performance

Published Jun 15, 2019
Improving Django's Model.save() performance

If you ever used Django in your career, you must have interacted with the Django ORM. It’s a terrific piece of software that has made writing database tables, setting foreign-keys and indexes super-easy.

For a recent project, I noticed Member.save() was executing two SQL queries, one for UPDATE and another one for INSERT. The two queries were being executed for the same .save() which was surprising since it was the first time the object was being created so there was no need for the UPDATE query to be run by the ORM.

class Member(models.Model):
 mid = models.PrimaryKey(default=gen_mid)
    name = models.CharField(max_length=200)

Upon further inspection and going through Django’s Model Instance documentation, I came across this line:

If the object’s primary key attribute is set to a value that evaluates to True (i.e., a value other than None or the empty string), Django executes an UPDATE.
If the object’s primary key attribute is not set or if the UPDATE didn’t update anything (e.g. if the primary key is set to a value that doesn’t exist in the database), Django executes an INSERT.

Since I was generating a default value for the primary key of the Member model, the ORM was executing an UPDATE first (which was failing) and then doing an INSERT on the database. The Django documentation also explains the workaround for this problem

In some rare circumstances, it’s necessary to be able to force the save() method to perform an SQL INSERT and not fall back to doing an UPDATE. Or vice-versa: update, if possible, but not insert a new row. In these cases, you can pass the force_insert=True or force_update=True parameters to the save() method. Passing both parameters is an error: you cannot both insert and update at the same time!

That was it. Just changing from Member.save() to Member.save(force_insert=True) when I was sure that a new object was being created, changed it from an UPDATE or INSERT query to just an INSERT query. Just the behavior I expected.

Django continues to be a fantastic web-framework with their documentation holding relevant of information that can lead to significant performance gains. Someone starting out with Django probably doesn’t have to worry about using force_insert or force_update and that’s the beauty. It just works!

Discover and read more posts from Udit Agarwal
get started