**`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:
```python
# "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:
```python
# "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")
```
```python
# "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:
```python
# "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:
```python
# "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:
```python
# "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:
```python
# "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:
```python
# "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")
```
```python
# "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:
```python
# "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"**][1]:
[![enter image description here][4]][4]
Now, I remove **`first()`** to use **`update()`** as shown below:
```python
# "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:
[![enter image description here][5]][5]
And, I have **`test` view** with **`save()`** and **`select_for_update().get(pk=1)`** as shown below:
```python
# "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:
[![enter image description here][2]][2]
Now, I remove **`get()`** to use **`update()`** as shown below:
```python
# "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:
[![enter image description here][3]][3]
So, **`save()`** with **`select_for_update()`** can run **`SELECT FOR UPDATE` query** while **`update()`** with **`select_for_update()`** cannot.
[1]:
[To see links please register here]
[2]:
[3]:
[4]:
[5]: