--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


Attachment: pgplL769T8tEd.pgp
Description: PGP signature

Reply via email to