Are there any other cases which "select_for_update()" doesn't work in Django?

When using select_for_update() with update() as shown below. *I use Django 3.2.16:

# "store/views.py"

from django.db import transaction
from .models import Person
from django.http import HttpResponse

@transaction.atomic
def test(request):
                        # Here                    # Here
    print(Person.objects.select_for_update().all().update(name="Tom"))
                        # Here                           # Here
    print(Person.objects.select_for_update().filter(id=1).update(name="Tom"))
                                                  
    return HttpResponse("Test")

Only UPDATE query is run without SELECT FOR UPDATE query as shown below. *I use PostgreSQL and these logs below are the queries of PostgreSQL and you can check On PostgreSQL, how to log queries with transaction queries such as "BEGIN" and "COMMIT":

enter image description here

While when using select_for_update() with save() 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):
                            # Here
    person1 = Person.objects.select_for_update().all().first()
    person1.name = "Tom"
    person1.save() # Here
                            # Here
    person2 = Person.objects.select_for_update().filter(id=1).first()
    person2.name = "Tom"
    person2.save() # Here
                            # Here
    person3 = Person.objects.select_for_update().get(id=1)
    person3.name = "Tom"
    person3.save() # Here

    return HttpResponse("Test")

SELECT FOR UPDATE query and UPDATE query are run as shown below:

enter image description here

And, when using select_for_update() with count() 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):
                        # Here                    # Here
    print(Person.objects.select_for_update().all().count())
                        # Here                           # Here
    print(Person.objects.select_for_update().filter(id=1).count())

    return HttpResponse("Test")

SELECT query is run instead of SELECT FOR UPDATE query as shown below:

enter image description here

While when using select_for_update() with len() 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):
        # Here              # Here               
    print(len(Person.objects.select_for_update().all()))
        # Here              # Here
    print(len(Person.objects.select_for_update().filter(id=1)))

    return HttpResponse("Test")

SELECT FOR UPDATE query is run instead of SELECT query as shown below:

enter image description here

So, are there any other cases which select_for_update() doesn't work in Django in addition to what I've shown above?

Yes, there are other cases which select_for_update() doesn't work in Django.

When using select_for_update() with delete() of a queryset 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):
                        # Here              # Here
    print(Person.objects.select_for_update().delete())
                        # Here                    # Here
    print(Person.objects.select_for_update().all().delete())
                        # Here                           # Here
    print(Person.objects.select_for_update().filter(id=1).delete())

    return HttpResponse("Test")

Only DELETE query is run without SELECT FOR UPDATE query as shown below.

enter image description here

While when using select_for_update() with delete() of an object 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):
                        # Here              # Here
    print(Person.objects.select_for_update().first().delete())

    # Or
                        # Here                            # Here    
    print(Person.objects.select_for_update().all().first().delete())
    
    # Or
                        # Here                                   # Here
    print(Person.objects.select_for_update().filter(id=1).first().delete())

    # Or
                        # Here                        # Here
    print(Person.objects.select_for_update().get(id=1).delete())

    return HttpResponse("Test")

SELECT FOR UPDATE query and DELETE query are run as shown below:

enter image description here

enter image description here

enter image description here

enter image description here

Back to Top