いくつかのアイテムを持ついくつかのグループがあるとします。グループ内でアイテムに一意のインデックスを付けたい:
class Item(models.Model):
group = models.ForeignKey(Group, null=True)
index = models.IntegerField(default=0)
class Meta:
unique_together=('group','index')
def save(self):
if self.pk is None and self.group_id is not None:
self.thread_index = Item.objects.filter(group_id=group_id).count()+1
return super(Item, self).save()
しかし、更新はアトミックではないため、これには問題があります。つまり、thread_index を計算した後、データベースに書き込む前に、別のトランザクションが別の行を追加した可能性があります。
IntegrityError をキャッチして再試行することで動作させることができることを理解しています。しかし、次のようなSQLを使用して、挿入コマンドの一部としてアトミックにデータを入力する良い方法があるかどうか疑問に思います。
insert into app_item (group, index)
select 25, count(*) from app_item where group_id=25