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
def add_sibling ( self , pos = None , ** kwargs ) : pos = self . _prepare_pos_var_for_add_sibling ( pos ) if len ( kwargs ) == 1 and 'instance' in kwargs : newobj = kwargs [ 'instance' ] if newobj . pk : raise NodeAlreadySaved ( "Attempted to add a tree node that is " "already in the database" ) else : 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 if sql : cursor = self . _get_database_cursor ( 'write' ) cursor . execute ( sql , params ) newobj . save ( ) return newobj
Adds a new node as a sibling to the current node object.