Идея выше
updated = Entry.objects.filter(Q(id=e.id) && Q(version=e.version))\
.update(updated_field=new_value, version=e.version+1)
if not updated:
raise ConcurrentModificationException()
отлично выглядит и должен работать даже без сериализуемых транзакций.
Проблема заключается в том, как расширить поведение по умолчанию .save (), чтобы не выполнять ручную сантехнику для вызова метода .update ().
Я посмотрел на идею Custom Manager.
Мой план - переопределить метод Manager _update, который вызывается Model.save_base () для выполнения обновления.
Это текущий код в Django 1.3
def _update(self, values, **kwargs):
return self.get_query_set()._update(values, **kwargs)
Что нужно сделать ИМХО это что-то вроде:
def _update(self, values, **kwargs):
#TODO Get version field value
v = self.get_version_field_value(values[0])
return self.get_query_set().filter(Q(version=v))._update(values, **kwargs)
Подобное должно происходить при удалении. Однако удалить это немного сложнее, так как Django реализует в этой области довольно много вуду через django.db.models.deletion.Collector.
Странно, что современному инструменту, такому как Django, не хватает руководства для Optimictic Concurency Control.
Я обновлю этот пост, когда решу загадку. Надеемся, что решение будет в хорошем питоническом ключе, не включающем тонны кодирования, странных представлений, пропуска основных частей Django и т. Д.