Are consecutive django model save calls safe?
I'm having trouble with a field that seems to sometimes not update. Just want to know if the following is unsafe on a Django model instance.
obj.field1 = True
obj.save()
obj.field2 = True
obj.save()
Since I'm not calling obj.update_from_db() is there any risk the second save resets/overrides field1
?
There are no post_save hooks involved, the surrounding code is synchronous and the DB backend is PostgreSQL.
Also, is save() synchronous (in the sense that the DB update will happen before the function returns)?
If you use PyCharm, you can always go ctrl+b
and inspect the function.
From what I can see, there is no await, no async, so it should be synchronous.
Anyway. This may be a little problem once you deploy it for example on Apache
and make like 2 or more instances. If these multiple instances uses same db there may be some issue. But usually this problematics is solved on db side (if you use just the "known" ones).
Answer: should be safe to use.
.save()
is generally speaking strictly synchronous. Which is to say that when you call .save()
, the commit will succeed before the method returns (or it will fail and the method will throw an exception).
There are a few situations where you this won't necessarily be the case (but they're more towards the advanced side of use-cases):
with transaction.atomic()
context - the.save()
can succeed (and return!) but persistence doesn't get attempted until the end of the transaction- Similar to the above, if you're operating on a table that has a
DEFERRABLE INITIALLY DEFERRED
constraint, Postgres will only persist the changes to that column at the end of the transaction - Depending a little bit on the logical setup of your app, isolation levels can unfortunately matter. Meaning that for all but the strictest one, you can engineer situations where
.save()
returns synchronously but your data fetching after-the-fact can see "wrong" data (different isolation levels will have different patterns to create this scenario). They're all related to reads happening concurrently with writes, so it's a problem you'd expect to find usually only at high volume and with low frequency. This isn't a problem with.save()
itself, but rather a note that it's hypothetically possible that.save()
works exactly as expected but with unexpected data reads during/afterwards.
The model.save() command saves all field information of the current model in db.
If you want to save only specific fields, add update_fields information.
model.save(update_fields=['aaa'])
As recommended by django.seolpyo.com
I found the issue was resolved by limiting update_fields
to only the fields I was changing. This resolved some race conditions when different processes worked on the same model but different fields. Just calling save()
without restricting the fields often meant stale data was being written back over recently updated ones.
If your program is single-threaded this usually won't be an issue but in my case 2 different processes were operating on the same model.