-
Наверняка такое уже обсуждалось, но не могу придумать, по каким ключевым словам искать.
Допустим у нас есть некий вопрос.
class Question(models.Model): text = ...
Ответы мы принимаем до тех пор, пока не определимся с правильным ответом.
Например:
class UnapprovedAnswer(models.Model): question = models.ForeignKey(Question) text = ...
и
class ApprovedAnswer(models.Model): question = models.ForeignKey(Question, unique=True) text = ...
Мы должны выбрать UnapprovedAnswer и создать на его основе ApprovedAnswer. При этом все UnapprovedAnswer к этому Question нужно удалить.
Как это сделать и быть уверенным, что праллельно у нас не появился новых ответов? Или иными словами как атомарно проверить отсутствие ApprovedAnswer и создать UnapprovedAnswer?
Спасибо.
P.S. Модели не обязательно таким образом должны быть построены. Главное — идея. -
Вас спасут два
BooleanField:-)Очевидно, что такая модель ответов концептуально некрасива. Ответ дожен быть представлен одной моделью с пометкой, какой из множества для вопроса верен.
Нужно блокировать вопрос при поступлении правильного ответа. Поэтому ему тоже флажок повесить.
-
Александр, мне кажется таким образом мы просто меняем один race condition на другой. Флажки же тоже нужно успевать проверять/проставлять.
Можно вас попросить привести более конкретный пример? -
Средставами
ORMневозможно заблокировать выбранные строки для последующего изменения (как в некоторых СУБД например произходит приSELECT FOR UPDATE).Следовательно, вы маркируете каждый ответ временем создания, при поступлении правильного, отмечаете вопрос как решенный и берете самый старый из правильных ответов(если не повезло и их несколько).
Или просто опускаетесь до raw sql и делатет блокировку.
-
Мне кажется, что здесь надо использовать версионность. То есть к вопросу добавить поле версии типа интежер и инкрементировать его при поступлении каждого нового ответа. Далее применить http://softwaremaniacs.org/blog/2009/01/14/changed-data-in-forms/ - это поможет определить есть ли новые ответы или нет. Возможно в модель надо добавить флаг approved, чтобы нельзя было добавлять новые ответы. Хотя в этом случае проблема с блокировкой остается, но ее можно победить у Ивана было написано про блокировку на основе файлов.
-
Извиняюсь:
>Возможно в модель надо добавить флаг approved
читать как:
Возможно в модель вопроса надо добавить флаг approved -
Хотя в этом случае проблема с блокировкой остается, но ее можно победить у Ивана было написано про блокировку на основе файлов.
На самом деле,
select for updateпопроще. Например не надо думать про освобождение лока, он снимается с завершением транзакции. -
А select for update в django есть?
-
В ORM пока нет. Но ничто не мешает сделать его вручную:
from django.db import connection cursor = connection.cursor() cursor.execute('begin') cursor.execute('select 1 from some_table where id = %s for update', [id]) -
Если уж делать как предлагает Ваня - то в кастомном менеджере с выбором имени таблицы и primary key поля.
Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.



