tree_id が重複して登録されていまう問題
- 多重処理を行っている時に発生することがある模様
class TreeManager(models.Manager.from_queryset(TreeQuerySet)):
...
@delegate_manager
def insert_node(self, node, target, position='last-child', save=False,
allow_existing_pk=False, refresh_target=True):
if node.pk and not allow_existing_pk and self.filter(pk=node.pk).exists():
raise ValueError(_('Cannot insert a node which has already been saved.'))
if target is None:
tree_id = self._get_next_tree_id()
setattr(node, self.left_attr, 1)
setattr(node, self.right_attr, 2)
setattr(node, self.level_attr, 0)
setattr(node, self.tree_id_attr, tree_id)
setattr(node, self.parent_attr, None)
...
def _get_next_tree_id(self):
max_tree_id = list(self.aggregate(Max(self.tree_id_attr)).values())[0]
max_tree_id = max_tree_id or 0
return max_tree_id + 1
...
ロックをかける
django-mptt で tree_id の採番に関して、テーブルロックをかけることは可能です。django-mptt は、デフォルトでは、tree_id の採番にテーブルロックをかけていませんが、以下のようにして、テーブルロックをかけることができます³。
from django.db import transaction
with transaction.atomic():
# ロックをかけたい処理
このように、transaction.atomic() を使うことで、トランザクションを開始し、その中で行われる処理に対してロックをかけることができます。³
ソース: Bing との会話 2023/4/25
- (1) Concurrency and pre-calculated tree_id #555 - Github. https://github.com/django-mptt/django-mptt/issues/555.
- (2) Django で自動採番された id を使用する | コーヒー飲みながら仕事 … https://coffee-nominagara.com/django-autoincrement-id.
- (3) 【Django】model の主キーにAutoFieldを設定しても自動採番し … https://teratail.com/questions/221566.
tree_id を UUIDにするには?
uuid を生成して 整数に変換する -> 値が大きすぎる :
In [1]: import uuid
...:
In [2]: int(uuid.uuid4())
Out[2]: 89403620638132928549772421778270623272