tree_id が重複して登録されていまう問題

  • 多重処理を行っている時に発生することがある模様
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
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 の採番にテーブルロックをかけていませんが、以下のようにして、テーブルロックをかけることができます³。

1
2
3
4
from django.db import transaction

with transaction.atomic():
    # ロックをかけたい処理

このように、transaction.atomic() を使うことで、トランザクションを開始し、その中で行われる処理に対してロックをかけることができます。³

ソース: Bing との会話 2023/4/25

tree_id を UUIDにするには?

uuid を生成して 整数に変換する -> 値が大きすぎる :

1
2
3
4
5
In [1]: import uuid
   ...: 

In [2]: int(uuid.uuid4())
Out[2]: 89403620638132928549772421778270623272