--On 30. Dezember 2007 18:02:13 -0500 Michael Bayer <[EMAIL PROTECTED]> wrote:
I am using this model since some years for the application (hand- made Python code/SQL queries) but now I want to adopt it to SA. The basic question is how I would extend the configuration for the self-referential mapper in order to make Tree 1 appear as: A / \ B N / | |\ D E P Q To make it more clear: when obtaining the list of children for node 'A' I want to get hold of the rows for the nodes 'B' and 'N', not 'B' and 'C'. So the node 'C' should be replaced with the node 'N' and its subtree. Any idea how to model this in a sane way using SA?without seeing much detail here it seems like youd just have a relation along "share_id", which im assuming is a different kind of relation than the one from A to B, and to "conceal" the C node and make it look like an N you could use a proxying class attribute. or you could do something similar at the SQL level by using a more elaborate "primaryjoin" condition from parent node to child node, which tests for the presence of "share_id" - possibly using a "viewonly" relation which is separate from the "persistence" relation if you also need to set up the "C" node attached to "A" explicitly for a flush operation.
I found a perfectly solution for this issue. The mapper looks like this: mapper(HierarchiesNode, HierarchiesTable, properties={ '_children' : relation( HierarchiesNode, primaryjoin=and_(HierarchiesTable.c.parent_id==HierarchiesTable.c.id), order_by=[HierarchiesTable.c.pos], cascade="all", viewonly=True, # working??backref=backref("parent", remote_side=[HierarchiesTable.c.id])
and the HierarchiesNode class provides a propery 'children' that deals with links to other nodes: @property def children(self): lst = list() for n in self._children: # pointer (id) of a shared node back to its # original node within the current tree n.referenced_by_id = None if n.hierarchyshare_id is None: # node does not reference another node (no share) lst.append(n) else: # node points to another node -> obtain the referenced# node and return it as current child instead of the original
# node session = object_session(self)shared_node = session.query(HierarchiesNode).filter_by(HierarchiesNode.c.id==n.hierarchyshare_id).one()
shared_node.referenced_by_id = n.id lst.append(shared_node) return lst So 'children' basically return the list of child nodes where nodes pointing to other trees are replaced with the referenced node.This works fine as read-only data-structure. Modifications of the tree structure itself happen outside (given by the nature of the whole application).
Andreas
pgplL769T8tEd.pgp
Description: PGP signature