On Apr 11, 2012, at 3:34 AM, lars van gemerden wrote: > Hi all, > > I am looking for a way to append a child to a tree like structure. I > am using adjacency to represent the tree. > > Let's say I have a relationship configured with: > > children = relationship(TreeNode, > primaryjoin = "TreeNode.id == > TreeNode.parent_id", > backref = backref( "parent", > remote_side=[TreeNode.id]), > cascade = "all, delete-orphan", > use_list = True) > > and I do: > > t1 = TreeNode() > t2 = TreeNode(parent = t1) > t3 = TreeNode(parent = t2) > > then i can set: > > t1.parent = t3, > > without problem, but: > > t3.children.append(t1) > > gives a CircularDependencyError, while i would like this to give the > same result as t1.parent = t3, perhaps by altering the behaviour of > Treenode.children.append. > > Am I missing something? > Is there some way to arrange for this?
t1.parent = t3 means you aren't persisting a tree anymore - it's no longer a hierarchy, since t3 is a descendant of t1 already via t2. It's a cycle. The exception on the "children" side is probably because mutating "children" has the effect of both t3 and t1 being considered in the flush (due to t3.children as well as t1.parent_id changing), whereas t1.parent = t3 does not actually consider "t3" to modified. You'd still get a cycle if you created everything via "x.parent=y" at once (below I just put it into the adjacency_list.py example - boom): node = TreeNode('rootnode') n1 = TreeNode('node1', parent=node) n2 = TreeNode('node2', parent=n1) node.parent = n2 session.add(node) session.flush() sqlalchemy.exc.CircularDependencyError: Circular dependency detected. Cycles: ... though I wasn't able to reproduce the behavior being different by mutating children vs. the parent....I'm sure with more digging I could figure that out. But in any case, you aren't safe from cycles if you're building them, the usual way to insert rows with cycles to themselves is to use the post_update feature described at http://docs.sqlalchemy.org/en/latest/orm/relationships.html#rows-that-point-to-themselves-mutually-dependent-rows . You probably need to put it on both sides in this case as the unit of work code will consider one or both of the "children" or "parent" relationships in a particular flush depending on where it sees changes. -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to sqlalchemy@googlegroups.com. To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.