Reputation: 125
# /uri/one/{pk}/
class ModelOneView(generic.View):
def post(self, request, pk): # pk has the same value as below
Model.objects.filter(pk=pk).update(name=request.POST['name'])
return HttpResponse(status=200)
# /uri/two/{pk}/
class ModelTwoView(generic.View):
def post(self, request, pk): # pk has the same value as above
Model.objects.filter(pk=pk).update(bool_field=True)
return HttpResponse(status=200)
I simplified my code a little but basically what I'm doing is that I have two different URIs that both perform some changes on the very same model (not the same field though). The problem here is that my client is calling them both basically the same time.
// script.js in my index.html
function notHealthyForDjango() {
callFirstURI();
callSecondURI();
}
Neither Django nor Client throw any errors at any point, I receive the OK responses. However, the changes I attempt to do with the callFirstURI(); never reach the database. But when I comment out the callSecondURI();
function notHealthyForDjango() {
callFirstURI();
//callSecondURI();
}
Now the call to the first URI works as intended!
How can I solve this problem? I'm using psql, Python 2.7 and Django 1.9. How can I modify my models' fields without the risk of such collisions?
EDIT
I'd like to find a server side solution for the problem, instead of just timing my Client's javascript requests more favorably.
Upvotes: 1
Views: 135
Reputation: 53734
Have you considered select_for_update ?
Returns a queryset that will lock rows until the end of the transaction, generating a SELECT ... FOR UPDATE SQL statement on supported databases.
Supported databases are Postgresql, Oracle and Mysql. I notice that you haven't mentioned your database. Though sqlite isn't supported it's rarely a problem at least on linux because file locking will make sure that the same data doesn't get over written with sqlite.
You will need to use this with an atomic transaction for best results.
def post(self, request, pk): # pk has the same value as below
with transaction.atomic():
Model.objects.select_for_update().filter(pk=pk).update(
name=request.POST['name'])
return HttpResponse(status=200)
Upvotes: 1
Reputation: 6980
Two suggestions you might like to try:
Run callSecondURI()
after completion of callFirstURI()
using a callback in your AJAX request
It might not apply (I am by no means an expert on this) but this sounds like it could be to do with multithreading. Have a look at this question for a decorator that deals with this.
Upvotes: 0