Итак, есть несколько способов сделать то, что вы просите. Но многие из них не будут зависеть от реализации: вы можете использовать блокировки или блокировки, но они действительно будут работать только на 100% -ных многопоточных серверах и, вероятно, вообще не будут реализованы в реализации fork / pre-fork.
Это более или менее означает, что реализация блокировки будет зависеть от вас. Две идеи:
.lock
файл в вашей файловой системе
locked
собственность в вашем классе модели
В обоих случаях необходимо вручную установить объект блокировки при обновлении и проверить его при удалении. Попробуйте что-то вроде:
def safe_update(request,model,id):
obj = model.objects.get(id)
if obj.locked:
raise SimultaneousUpdateError #Define this somewhere
else:
obj.lock()
return update_object(request,model,id)
# In models file
class SomeModel(models.Model):
locked = models.BooleanField(default = False)
def lock(self):
self.locked = True
super(models.Model,self).save()
def save(self):
# overriding save because you want to use generic views
# probably not the best idea to rework model code to accomodate view shortcuts
# but I like to give examples.
self.locked = False
# THIS CREATES A DIFFERENT CRITICAL REGION!
super(models.Model,self).save()
Это действительно неуклюжая реализация, которую вам придется очистить. Возможно, вас не устраивает тот факт, что была создана другая критическая область, но я не понимаю, как вы будете работать намного лучше, если будете использовать базу данных в качестве реализации, не усложняя реализацию. (Одним из вариантов будет сделать блокировки полностью отдельными объектами. Затем вы можете обновить их после вызова метода save (). Но я не чувствую необходимости кодировать это.) Если вы действительно хотите использовать блокировку на основе файлов система, которая также решит проблему. Если вы параноик по базе данных, это может быть для вас. Что-то вроде:
class FileLock(object):
def __get__(self,obj):
return os.access(obj.__class__+"_"+obj.id+".lock",os.F_OK)
def __set__(self,obj,value):
if not isinstance(value,bool):
raise AttributeError
if value:
f = open(obj.__class__+"_"+obj.id+".lock")
f.close()
else:
os.remove(obj.__class__+"_"+obj.id+".lock")
def __delete__(self,obj):
raise AttributeError
class SomeModel(models.Model):
locked = FileLock()
def save(self):
super(models.Model,self).save()
self.locked = False
В любом случае, может быть, есть какой-то способ смешать и сопоставить эти предложения на ваш вкус?