42

As the Django Documentation says, select_for_update returns a Queryset. But get does not. Now I have a query which I am sure is going to return only one tuple. But I also need to acquire locks for this transaction. So I am doing something like:

ob = MyModel.objects.select_for_update().filter(some conditions)

Now, I need to modify some values of ob. But ob is a Queryset. This seems pretty simple, but beats me. I'm pretty new to Django. Some advice please.

Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
Indradhanush Gupta
  • 4,067
  • 10
  • 44
  • 60

3 Answers3

60

Just call get, slice it, etc. and save as usual. The lock is in place through the transaction.

ob = MyModel.objects.select_for_update().get(pk=1)

Any changes are committed at the end of the transaction (which by default through 1.5 is per-request)

Yuji 'Tomita' Tomita
  • 115,817
  • 29
  • 282
  • 245
45

You can also use select_for_update with get_object_or_404 function:

from django.db import transaction
from django.shortcuts import get_object_or_404

with transaction.atomic():
    obj = get_object_or_404(MyModel.objects.select_for_update(), pk=pk)
    # do some stuff with locked obj
Community
  • 1
  • 1
Omid Raha
  • 9,862
  • 1
  • 60
  • 64
1

Just after select_for_update().filter(), you can put .first() which returns the 1st object of a queryset to update it with save() as shown below. *You can see my question and answer explaining more about select_for_update() in Django:

                                                                # Here
ob = MyModel.objects.select_for_update().filter(some conditions).first()
ob.field_1 = 'some value'
ob.save()
Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129