save()
:
- can be used with model object but not with
QuerySet
or Manager
objects.
- with
select_for_update()
can run SELECT FOR UPDATE
query.
update()
- can be used with
QuerySet
or Manager
objects but not with model object.
- with
select_for_update()
cannot run SELECT FOR UPDATE
query.
For example, I have Person
model as shown below:
# "store/models.py"
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=30)
def __str__(self):
return self.name
Then, you can use save()
with Person
model object as shown below:
# "store/views.py"
from .models import Person
from django.http import HttpResponse
def test(request):
person = Person.objects.get(id=1)
person.name = 'Tom'
person.save() # Here
return HttpResponse("Test")
# "store/views.py"
from .models import Person
from django.http import HttpResponse
def test(request):
person = Person.objects.filter(pk=1).first()
person.name = 'Tom'
person.save() # Here
return HttpResponse("Test")
But, you cannot use save()
with QuerySet
object as shown below:
# "store/views.py"
from .models import Person
from django.http import HttpResponse
def test(request):
person = Person.objects.filter(pk=1)
person.name = 'Tom'
person.save() # Here
return HttpResponse("Test")
Then, the error below occurs:
AttributeError: 'QuerySet' object has no attribute 'save'
And, you cannot use save()
with Manager
object as shown below:
# "store/views.py"
from .models import Person
from django.http import HttpResponse
def test(request):
person = Person.objects
person.name = 'Tom'
person.save() # Here
return HttpResponse("Test")
Then, the error below occurs:
AttributeError: 'Manager' object has no attribute 'save'
Then, you can use update()
with QuerySet
object as shown below:
# "store/views.py"
from .models import Person
from django.http import HttpResponse
def test(request):
person = Person.objects.filter(pk=1)
person.update(name="Tom") # Here
return HttpResponse("Test")
And, you can use update()
with Manager
object as shown below:
# "store/views.py"
from .models import Person
from django.http import HttpResponse
def test(request):
person = Person.objects
person.update(name="Tom") # Here
return HttpResponse("Test")
But, you cannot use update()
with Person
model object as shown below:
# "store/views.py"
from .models import Person
from django.http import HttpResponse
def test(request):
person = Person.objects.get(id=1)
person.update(name="Tom") # Here
return HttpResponse("Test")
# "store/views.py"
from .models import Person
from django.http import HttpResponse
def test(request):
person = Person.objects.filter(pk=1).first()
person.update(name="Tom") # Here
return HttpResponse("Test")
Then, the error below occurs:
AttributeError: 'Person' object has no attribute 'update'
Next for example, select_for_update()
is used to prevent race condition(lost update or write skew) when updating data in Django.
And, I have test
view with save()
and select_for_update().filter(pk=1).first()
as shown below:
# "store/views.py"
from django.db import transaction
from .models import Person
from django.http import HttpResponse
@transaction.atomic
def test(request):
person = Person.objects.select_for_update().filter(pk=1).first() # Here
person.name = 'Tom'
person.save() # Here
return HttpResponse("Test")
Then, when I run test
view, SELECT FOR UPDATE
and UPDATE
queries are run as shown below. *I used PostgreSQL and these logs below are the query logs of PostgreSQL and you can check On PostgreSQL, how to log SQL queries with transaction queries such as "BEGIN" and "COMMIT":

Now, I remove first()
to use update()
as shown below:
# "store/views.py"
from django.db import transaction
from .models import Person
from django.http import HttpResponse
@transaction.atomic
def test(request):
person = Person.objects.select_for_update().filter(pk=1) # Here
person.update(name="Tom") # Here
return HttpResponse("Test")
Then, when I run test
view, SELECT FOR UPDATE
query is not run and only UPDATE
query is run as shown below:

And, I have test
view with save()
and select_for_update().get(pk=1)
as shown below:
# "store/views.py"
from django.db import transaction
from .models import Person
from django.http import HttpResponse
@transaction.atomic
def test(request):
person = Person.objects.select_for_update().get(pk=1) # Here
person.name = 'Tom'
person.save() # Here
return HttpResponse("Test")
Then, when I run test
view, SELECT FOR UPDATE
and UPDATE
queries are run as shown below:

Now, I remove get()
to use update()
as shown below:
# "store/views.py"
from django.db import transaction
from .models import Person
from django.http import HttpResponse
@transaction.atomic
def test(request):
person = Person.objects.select_for_update() # Here
person.update(name="Tom") # Here
return HttpResponse("Test")
Then, when I run test
view, SELECT FOR UPDATE
query is not run and only UPDATE
query is run as shown below:

So, save()
with select_for_update()
can run SELECT FOR UPDATE
query while update()
with select_for_update()
cannot.