Короткий ответ, это действительно не вопрос Django, как представлено.
Контроль параллелизма часто представляется как технический вопрос, но во многих отношениях является вопросом функциональных требований. Как вы хотите / нужно ваше приложение для работы? До тех пор, пока мы не узнаем об этом, будет трудно дать какой-либо конкретный совет Джанго.
Но я чувствую себя бессвязным, так что вот так ...
Есть два вопроса, которые я обычно задаю себе, когда сталкиваюсь с необходимостью контроля параллелизма:
- Насколько вероятно, что двум пользователям потребуется одновременно изменить одну и ту же запись?
- Какое влияние оказывает пользователь, если его / ее изменения в записи будут потеряны?
Если вероятность столкновений относительно высока или последствия потери модификации серьезны, то вы можете рассматривать какую-то форму пессимистической блокировки. В пессимистической схеме каждый пользователь должен получить логическую блокировку до открытия записи для модификации.
Пессимистическая блокировка сопряжена с большими сложностями. Вы должны синхронизировать доступ к блокировкам, учитывать отказоустойчивость, срок действия блокировки, могут ли блокировки быть отменены суперпользователями, могут ли пользователи видеть, у кого есть блокировка, и так далее.
В Django это может быть реализовано с помощью отдельной модели блокировки или какого-то внешнего ключа «блокировки пользователя» для заблокированной записи. Использование таблицы блокировок дает вам немного больше гибкости с точки зрения хранения, когда блокировка была получена, пользователя, заметок и т. Д. Если вам нужна универсальная таблица блокировок, которую можно использовать для блокировки любого типа записи, посмотрите на django.contrib.contenttypes framework , но быстро это может перерасти в синдром абстракции астронавта.
Если коллизии маловероятны или потерянные модификации тривиально воссоздаются, то вы можете функционально избежать неприятностей с оптимистичными методами параллелизма. Этот метод прост и проще в реализации. По сути, вы просто отслеживаете номер версии или метку времени модификации и отклоняете любые модификации, которые вы обнаружили как неуместные.
С точки зрения функционального проектирования вам нужно только рассмотреть, как эти параллельные ошибки модификации представляются вашим пользователям.
В терминах Django оптимистическое управление параллелизмом может быть реализовано путем переопределения метода save в вашем классе модели ...
def save(self, *args, **kwargs):
if self.version != self.read_current_version():
raise ConcurrentModificationError('Ooops!!!!')
super(MyModel, self).save(*args, **kwargs)
И, конечно же, для того, чтобы любой из этих механизмов параллелизма был устойчивым, вы должны рассмотреть транзакционный контроль . Ни одна из этих моделей не является полностью работоспособной, если вы не можете гарантировать ACID-свойства своих транзакций.