Django select_for_update cannot be used outside of a transaction
Solution 1
The answer is in the error, wrap the query in a transaction
Django's documentation is located here: https://docs.djangoproject.com/en/dev/topics/db/transactions/#django.db.transaction.atomic
One approach is:
from django.db import transaction
def some_method():
with transaction.atomic():
job_qs = Job.objects.select_for_update().filter(pk=job.id)
for job in job_qs:
Solution 2
Addendum
As of Django 2.0, related rows are locked by default (not sure what the behaviour was before) and the rows to lock can be specified in the same style as select_related
using the of
parameter:
By default,
select_for_update()
locks all rows that are selected by the query. For example, rows of related objects specified inselect_related()
are locked in addition to rows of the queryset’s model. If this isn’t desired, specify the related objects you want to lock inselect_for_update(of=(...))
using the same fields syntax asselect_related()
. Use the value 'self' to refer to the queryset’s model.
https://docs.djangoproject.com/en/dev/ref/models/querysets/#select-for-update
Comments
-
Kingpin2k almost 2 years
I was using Django 1.5.1 and upgraded to Django 1.6.6.
In Django 1.5.1 I was using select for update to guarantee atomic execution.
job_qs = Job.objects.select_for_update().filter(pk=job.id) for job in job_qs:
Unfortunately this now throws an error:
File "/srv/venvs/django-picdoc/local/lib/python2.7/site-packages/django/db/models/query.py", line 96, in __iter__ self._fetch_all() File "/srv/venvs/django-picdoc/local/lib/python2.7/site-packages/django/db/models/query.py", line 857, in _fetch_all self._result_cache = list(self.iterator()) File "/srv/venvs/django-picdoc/local/lib/python2.7/site-packages/django/db/models/query.py", line 220, in iterator for row in compiler.results_iter(): File "/srv/venvs/django-picdoc/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 713, in results_iter for rows in self.execute_sql(MULTI): File "/srv/venvs/django-picdoc/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 776, in execute_sql sql, params = self.as_sql() File "/srv/venvs/django-picdoc/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 147, in as_sql raise TransactionManagementError("select_for_update cannot be used outside of a transaction.") TransactionManagementError: select_for_update cannot be used outside of a transaction.
What are some of the solutions for solving this?