1
# /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.

user3622167
  • 125
  • 1
  • 9
  • Did you try my suggestion? – e4c5 Jul 16 '16 at 12:32
  • I'm sorry I haven't had the time yet. I will be getting back to this later this week and see if this solves the problem. It seems very promising and I truly appreciate your help a lot! I apologize for the delay. – user3622167 Jul 17 '16 at 20:52
  • Glad to know it worked. Can't upvote your question today (out of votes, will do tomorrow) – e4c5 Jul 18 '16 at 14:10

2 Answers2

1

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)
e4c5
  • 52,766
  • 11
  • 101
  • 134
0

Two suggestions you might like to try:

  1. Run callSecondURI() after completion of callFirstURI() using a callback in your AJAX request

  2. 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.

Community
  • 1
  • 1
Jacob Windsor
  • 6,750
  • 6
  • 33
  • 49
  • Hey Jacob! Thank you for your response. Doing it as you write in your first recommendation works well. However, I'd like to find a server side solution for this problem if it's possible. My bad for not being clear on that. I'll check out your second recommendation a little later! – user3622167 Jul 10 '16 at 11:41
  • Hi, glad that I helped. If the solution worked then please consider accepting the answer, although I understand I did not give a server side approach – Jacob Windsor Jul 10 '16 at 18:50