コード例 #1
0
    def process(self):

        # do we have a root node already?
        last_root = self.cls.get_last_root_node()

        if last_root and last_root.node_order_by:
            # there are root nodes and node_order_by has been set
            # delegate sorted insertion to add_sibling
            return last_root.add_sibling('sorted-sibling', **self.kwargs)

        if last_root:
            # adding the new root node as the last one
            newpath = last_root._inc_path()
        else:
            # adding the first root node
            newpath = self.cls._get_path(None, 1, 1)

        if len(self.kwargs) == 1 and 'instance' in self.kwargs:
            # adding the passed (unsaved) instance to the tree
            newobj = self.kwargs['instance']
            if newobj.pk:
                raise NodeAlreadySaved("Attempted to add a tree node that is "\
                    "already in the database")
        else:
            # creating the new object
            newobj = self.cls(**self.kwargs)

        newobj.depth = 1
        newobj.path = newpath
        # saving the instance before returning it
        newobj.save()
        return newobj
コード例 #2
0
    def add_child(self, **kwargs):
        """Adds a child to the node."""
        cls = get_result_class(self.__class__)

        if len(kwargs) == 1 and 'instance' in kwargs:
            # adding the passed (unsaved) instance to the tree
            newobj = kwargs['instance']
            if newobj.pk:
                raise NodeAlreadySaved("Attempted to add a tree node that is "\
                    "already in the database")
        else:
            newobj = cls(**kwargs)

        try:
            newobj._cached_depth = self._cached_depth + 1
        except AttributeError:
            pass
        if not cls.node_order_by:
            try:
                max = cls.objects.filter(parent=self).reverse()[0].sib_order
            except IndexError:
                max = 0
            newobj.sib_order = max + 1
        newobj.parent = self
        newobj.save()
        return newobj
コード例 #3
0
    def add_root(cls, **kwargs):
        """Adds a root node to the tree."""

        # do we have a root node already?
        last_root = cls.get_last_root_node()

        if last_root and last_root.node_order_by:
            # there are root nodes and node_order_by has been set
            # delegate sorted insertion to add_sibling
            return last_root.add_sibling('sorted-sibling', **kwargs)

        if last_root:
            # adding the new root node as the last one
            newtree_id = last_root.tree_id + 1
        else:
            # adding the first root node
            newtree_id = 1

        if len(kwargs) == 1 and 'instance' in kwargs:
            # adding the passed (unsaved) instance to the tree
            newobj = kwargs['instance']
            if newobj.pk:
                raise NodeAlreadySaved("Attempted to add a tree node that is "\
                    "already in the database")
        else:
            # creating the new object
            newobj = get_result_class(cls)(**kwargs)

        newobj.depth = 1
        newobj.tree_id = newtree_id
        newobj.lft = 1
        newobj.rgt = 2
        # saving the instance before returning it
        newobj.save()
        return newobj
コード例 #4
0
ファイル: mp_tree.py プロジェクト: rhel/django-treebeard
    def process(self):
        if self.node.object_id != self.kwargs.get('object_id', False):
            raise KeyError(
                "The object_id for parent and child must be the same")

        if self.node_cls.node_order_by and not self.node.is_leaf():
            # there are child nodes and node_order_by has been set
            # delegate sorted insertion to add_sibling
            self.node.numchild += 1
            return self.node.get_last_child().add_sibling(
                'sorted-sibling', **self.kwargs)

        if len(self.kwargs) == 1 and 'instance' in self.kwargs:
            # adding the passed (unsaved) instance to the tree
            newobj = self.kwargs['instance']
            if newobj.pk:
                raise NodeAlreadySaved("Attempted to add a tree node that is "\
                    "already in the database")
        else:
            # creating a new object
            newobj = self.node_cls(**self.kwargs)

        newobj.depth = self.node.depth + 1
        if self.node.is_leaf():
            # the node had no children, adding the first child
            newobj.path = self.node_cls._get_path(self.node.path, newobj.depth,
                                                  1)

            # now we use Text instead varchar and this is extra check
            # max_length = self.node_cls._meta.get_field('path').max_length
            # if len(newobj.path) > max_length:
            #     raise PathOverflow(
            #         _('The new node is too deep in the tree, try'
            #           ' increasing the path.max_length property'
            #           ' and UPDATE your database'))
        else:
            # adding the new child as the last one
            newobj.path = self.node.get_last_child()._inc_path()
        # saving the instance before returning it
        newobj.save()
        newobj._cached_parent_obj = self.node

        get_result_class(self.node_cls).objects.filter(
            path=self.node.path,
            object_id=self.node.object_id).update(numchild=F('numchild') + 1)

        # we increase the numchild value of the object in memory
        self.node.numchild += 1
        return newobj
コード例 #5
0
    def add_child(self, **kwargs):
        """Adds a child to the node."""
        if not self.is_leaf():
            # there are child nodes, delegate insertion to add_sibling
            if self.node_order_by:
                pos = 'sorted-sibling'
            else:
                pos = 'last-sibling'
            last_child = self.get_last_child()
            last_child._cached_parent_obj = self
            return last_child.add_sibling(pos, **kwargs)

        # we're adding the first child of this node
        sql, params = self.__class__._move_right(self.tree_id,
                                                 self.rgt, False, 2)

        if len(kwargs) == 1 and 'instance' in kwargs:
            # adding the passed (unsaved) instance to the tree
            newobj = kwargs['instance']
            if newobj.pk:
                raise NodeAlreadySaved("Attempted to add a tree node that is "\
                    "already in the database")
        else:
            # creating a new object
            newobj = get_result_class(self.__class__)(**kwargs)

        newobj.tree_id = self.tree_id
        newobj.depth = self.depth + 1
        newobj.lft = self.lft + 1
        newobj.rgt = self.lft + 2

        # this is just to update the cache
        self.rgt += 2

        newobj._cached_parent_obj = self

        cursor = self._get_database_cursor('write')
        cursor.execute(sql, params)

        # saving the instance before returning it
        newobj.save()
        transaction.commit_unless_managed()

        return newobj
コード例 #6
0
    def add_sibling(self, pos=None, **kwargs):
        """Adds a new node as a sibling to the current node object."""
        pos = self._prepare_pos_var_for_add_sibling(pos)

        if len(kwargs) == 1 and 'instance' in kwargs:
            # adding the passed (unsaved) instance to the tree
            newobj = kwargs['instance']
            if newobj.pk:
                raise NodeAlreadySaved("Attempted to add a tree node that is "\
                    "already in the database")
        else:
            # creating a new object
            newobj = get_result_class(self.__class__)(**kwargs)

        if not self.node_order_by:
            newobj.sib_order = self.__class__._get_new_sibling_order(pos, self)
        newobj.parent_id = self.parent_id
        newobj.save()
        return newobj
コード例 #7
0
    def process(self):
        self.pos = self.node._prepare_pos_var_for_add_sibling(self.pos)

        if len(self.kwargs) == 1 and 'instance' in self.kwargs:
            # adding the passed (unsaved) instance to the tree
            newobj = self.kwargs['instance']
            if newobj.pk:
                raise NodeAlreadySaved("Attempted to add a tree node that is "\
                    "already in the database")
        else:
            # creating a new object
            newobj = self.node_cls(**self.kwargs)

        newobj.depth = self.node.depth

        if self.pos == 'sorted-sibling':
            siblings = self.node.get_sorted_pos_queryset(
                self.node.get_siblings(), newobj)
            try:
                newpos = siblings.all()[0]._get_lastpos_in_path()
            except IndexError:
                newpos = None
            if newpos is None:
                self.pos = 'last-sibling'
        else:
            newpos, siblings = None, []

        _, newpath = self.reorder_nodes_before_add_or_move(
            self.pos, newpos, self.node.depth, self.node, siblings, None,
            False)

        parentpath = self.node._get_basepath(newpath, self.node.depth - 1)
        if parentpath:
            self.stmts.append(
                self.get_sql_update_numchild(parentpath, 'inc'))

        self.run_sql_stmts()

        # saving the instance before returning it
        newobj.path = newpath
        newobj.save()

        return newobj
コード例 #8
0
    def add_root(cls, **kwargs):
        """Adds a root node to the tree."""

        if len(kwargs) == 1 and 'instance' in kwargs:
            # adding the passed (unsaved) instance to the tree
            newobj = kwargs['instance']
            if newobj.pk:
                raise NodeAlreadySaved("Attempted to add a tree node that is "\
                    "already in the database")
        else:
            newobj = cls(**kwargs)

        newobj._cached_depth = 1
        if not cls.node_order_by:
            try:
                max = get_result_class(cls).objects.filter(
                    parent__isnull=True).order_by(
                        'sib_order').reverse()[0].sib_order
            except IndexError:
                max = 0
            newobj.sib_order = max + 1
        newobj.save()
        return newobj
コード例 #9
0
    def add_sibling(self, pos=None, **kwargs):
        """Adds a new node as a sibling to the current node object."""

        pos = self._prepare_pos_var_for_add_sibling(pos)

        if len(kwargs) == 1 and 'instance' in kwargs:
            # adding the passed (unsaved) instance to the tree
            newobj = kwargs['instance']
            if newobj.pk:
                raise NodeAlreadySaved("Attempted to add a tree node that is "\
                    "already in the database")
        else:
            # creating a new object
            newobj = get_result_class(self.__class__)(**kwargs)

        newobj.depth = self.depth

        sql = None
        target = self

        if target.is_root():
            newobj.lft = 1
            newobj.rgt = 2
            if pos == 'sorted-sibling':
                siblings = list(
                    target.get_sorted_pos_queryset(target.get_siblings(),
                                                   newobj))
                if siblings:
                    pos = 'left'
                    target = siblings[0]
                else:
                    pos = 'last-sibling'

            last_root = target.__class__.get_last_root_node()
            if ((pos == 'last-sibling')
                    or (pos == 'right' and target == last_root)):
                newobj.tree_id = last_root.tree_id + 1
            else:
                newpos = {
                    'first-sibling': 1,
                    'left': target.tree_id,
                    'right': target.tree_id + 1
                }[pos]
                sql, params = target.__class__._move_tree_right(newpos)

                newobj.tree_id = newpos
        else:
            newobj.tree_id = target.tree_id

            if pos == 'sorted-sibling':
                siblings = list(
                    target.get_sorted_pos_queryset(target.get_siblings(),
                                                   newobj))
                if siblings:
                    pos = 'left'
                    target = siblings[0]
                else:
                    pos = 'last-sibling'

            if pos in ('left', 'right', 'first-sibling'):
                siblings = list(target.get_siblings())

                if pos == 'right':
                    if target == siblings[-1]:
                        pos = 'last-sibling'
                    else:
                        pos = 'left'
                        found = False
                        for node in siblings:
                            if found:
                                target = node
                                break
                            elif node == target:
                                found = True
                if pos == 'left':
                    if target == siblings[0]:
                        pos = 'first-sibling'
                if pos == 'first-sibling':
                    target = siblings[0]

            move_right = self.__class__._move_right

            if pos == 'last-sibling':
                newpos = target.get_parent().rgt
                sql, params = move_right(target.tree_id, newpos, False, 2)
            elif pos == 'first-sibling':
                newpos = target.lft
                sql, params = move_right(target.tree_id, newpos - 1, False, 2)
            elif pos == 'left':
                newpos = target.lft
                sql, params = move_right(target.tree_id, newpos, True, 2)

            newobj.lft = newpos
            newobj.rgt = newpos + 1

        # saving the instance before returning it
        if sql:
            cursor = self._get_database_cursor('write')
            cursor.execute(sql, params)
        newobj.save()

        return newobj