How to run "SELECT FOR UPDATE" instead of "SELECT" when changing and deleting data in Django Admin?

294 views Asked by At

I have the code below:

# "store/models.py"

from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=30)
# "store/admin.py"

from django.contrib import admin
from .models import Person

@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
    pass

Then, when changing data as shown below:

enter image description here

SELECT is run instead of SELECT FOR UPDATE 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

And, when clicking Delete button of Change person as shown below:

enter image description here

Then clicking Yes, I'm sure button to delete data as shown below:

enter image description here

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

enter image description here

Now, I want to run SELECT FOR UPDATE instead of SELECT for both cases as shown above.

So, how can I do this?

2

There are 2 answers

0
Super Kai - Kazuya Ito On

You need to override get_queryset() with select_for_update() as shown below:

# "store/admin.py"

from django.contrib import admin
from .models import Person

@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
    def get_queryset(self, request):
        qs = super().get_queryset(request)
        
        last_part_of_referer = request.META.get('HTTP_REFERER').split('/')[-2]
        last_part_of_uri = request.build_absolute_uri().split('/')[-2]

        if (last_part_of_referer == "change" and last_part_of_uri == "change") or \
           (last_part_of_referer == "delete" and last_part_of_uri == "delete"):
            qs = qs.select_for_update()
        
        return qs

Then, when changing data as shown below:

enter image description here

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

enter image description here

And, when clicking Delete button of Change person as shown below:

enter image description here

Then clicking Yes, I'm sure button to delete data as shown below:

enter image description here

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

enter image description here

0
Abhishek Sinha On

To run a SELECT FOR UPDATE query instead of a regular SELECT query in Django Admin, you can use the select_for_update() method on your queryset. This method will lock the rows in the queryset until the transaction is committed or rolled back, preventing other transactions from modifying the data in those rows.