33👍
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:
# "views.py"
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:
11👍
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
- [Django]-Django Cache cache.set Not storing data
- [Django]-Remove Labels in a Django Crispy Forms
- [Django]-How can I get MINIO access and secret key?
3👍
select_for_update()
must be run in a transaction.
So, use @transaction.atomic
for the view as shown below:
# "views.py"
from django.db import transaction
@transaction.atomic # Here
def some_method():
with transaction.atomic():
job_qs = Job.objects.select_for_update().filter(pk=job.id)
for job in job_qs:
Or, use with transaction.atomic():
in the view as shown below:
# "views.py"
from django.db import transaction
def some_method():
with transaction.atomic(): # Here
job_qs = Job.objects.select_for_update().filter(pk=job.id)
for job in job_qs:
Or, set 'ATOMIC_REQUESTS': True
to database settings in settings.py
as shown below:
# "settings.py"
DATABASES = {
'default':{
'ENGINE':'django.db.backends.postgresql',
'NAME':'postgres',
'USER':'postgres',
'PASSWORD':'admin',
'HOST':'localhost',
'PORT':'5432',
'ATOMIC_REQUESTS': True, # Here
},
}
- [Django]-Django dynamic forms – on-the-fly field population?
- [Django]-Django – how to unit test a post request using request.FILES
- [Django]-How can I get MINIO access and secret key?
-1👍
For me it happened even when using with transaction.atomic():
. The problem was that we didn’t set 'ATOMIC_REQUESTS': True
in the settings.py
file. Now this solved the problem.
As documented here: https://docs.djangoproject.com/en/3.1/topics/db/transactions/
"Set ATOMIC_REQUESTS
to True
in the configuration of each database for which you want to enable this behavior."
So in settings.py
we added:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': os.environ['DB_NAME'],
'USER': os.environ['DB_USER'],
'PASSWORD': os.environ['DB_PASSWORD'],
'HOST': os.environ['DB_HOST'],
'PORT': '3306',
'ATOMIC_REQUESTS': True
}
}
- [Django]-Combining Django F, Value and a dict to annotate a queryset
- [Django]-Django REST framework post array of objects
- [Django]-How to assign items inside a Model object with Django?