Really hoping someone can help---didn't get any responses on stackoverflow, 
and django docs don't seem to give an exact answer.


I have a bunch of views where I check if certain conditions are true before 
executing.   I'm concerned about one user using a view that changes the 
data after the condition has been checked in another view.  Do I need to 
use select_for_update in the code below? 


I'm using the setting ATOMIC_REQUESTS = True, to wrap each request in a 
transaction. My site is relatively low-traffic so I'm not concerned about 
performance yet. Using postgres as well.


*def feed_dog(self, dog_id):*
    dog = get_objects_or_404(Dog, pk=dog_id)
    if not dog.removed and not dog.fed_today:    *# line 3*
        *# do additional checks*
        dog.fed_today = True    *# line 5*
        dog.save()
        # also modify other related objects
        treat = Treats.objects.last()
        treat.dogs_being_fed_with_this_treat.add(dog)
        treat.save()
*def remove_dog_from_feed_list(self, dog_id):*
    dog = get_objects_or_404(Dog, pk=dog_id)
    if not dog.fed_today           *# line 12*
        dog.removed = True
        dog.save()
        treat.dogs_being_fed_with_this_treat.remove(dog)
        treat.save()

So my concern is that someone calls the feed_dog view, and then after line 
3 is checked but before line 5 is started, another user calls the 
remove_dog function. Since dog.fed_today is False still when user 2 is 
calling remove_dog, line 12 is True, and remove_dog view goes ahead and 
does dog.removed = True. At the same time the feed_dog view continues and 
sets dog.fed_today=True, adds the dog to the treat array, etc. So then I 
have an inconsistent state of dog.removed = True, and dog.fed_today = True.


Basically I need it so that certain attributes on the Dog model can't both 
be True at the same time, like dog.fed_today =True and dog.removed=True. I 
also have this related model Treat, where I don't want a dog object to have 
removed = True and also be in the treat.dogs_being_fed array.


Q:Is this a valid concern? Since transactions provide isolation, doesn't it 
mean that 1 of these views accesses the data either all before or all after 
the other one (they can't see the data in the half-done state)?


Q:What's the purpose of select_for_update, and would it help here? If 
transactions are already supposed to provide isolation, what's the purpose 
of select_for_update?


Q:Would it help to increase the isolation property of Django/Postgres from 
Read Committed?


Q:Would it help to have constraints on the Dog model itself (like having a 
def clean method that says a Dog can't be both removed=True and fed_today = 
True?). I'm mostly checking things in the views. Would this get reflected 
in a transaction? Would I also be able to create a constraint that reflects 
attributes in multiple models, like can't have dog.removed=True and have 
that dog be in the Treats.dogs_being_fed array?


Appreciate any help!

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/eb8b9a9c-aedc-43f7-8e7e-bcf43aed31fd%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to