from sqlalchemy import *
from sqlalchemy.orm import *
-from sqlalchemy.orm.collections import MappedCollection, collection_adapter
+from sqlalchemy.orm.collections import mapped_collection
from sqlalchemy.util import OrderedDict
engine = create_engine('sqlite:///:memory:', echo=True)
)
-class NodeList(OrderedDict, MappedCollection):
- """Mix OrderedDict and MappedCollection to create a dict-like collection class that keys off node names."""
-
- def __init__(self, *args, **kw):
- MappedCollection.__init__(self, keyfunc=lambda node: node.name)
- OrderedDict.__init__(self, *args, **kw)
-
class TreeNode(object):
"""a hierarchical Tree class, which adds the concept of a "root node". The root is
the topmost node in a tree, or in other words a node whose parent ID is NULL.
def __init__(self, name):
self.name = name
- self.children = NodeList()
self.root = self
- self.parent = None
- self.id = None
- self.data =None
- self.parent_id = None
- self.root_id=None
def _set_root(self, root):
self.root = root
def append(self, node):
if isinstance(node, str):
node = TreeNode(node)
- node.parent = self
node._set_root(self.root)
self.children.append(node)
else:
if isnew or selectcontext.populate_existing:
parentnode = selectcontext.identity_map[mapper.identity_key(instance.parent_id)]
- collection_adapter(parentnode.children).append_without_event(instance)
- # fire off lazy loader before the instance is part of the session
- instance.children
+ parentnode.children.append(instance)
return False
class TreeData(object):
name=trees.c.node_name,
parent_id=trees.c.parent_node_id,
root_id=trees.c.root_node_id,
- root=relation(TreeNode, primaryjoin=trees.c.root_node_id==trees.c.node_id, remote_side=trees.c.node_id, lazy=None, uselist=False),
- children=relation(TreeNode, primaryjoin=trees.c.parent_node_id==trees.c.node_id, lazy=None, uselist=True, cascade="delete,save-update", collection_class=NodeList),
- data=relation(mapper(TreeData, treedata, properties=dict(id=treedata.c.data_id)), cascade="delete,delete-orphan,save-update", lazy=False)
+ root=relation(TreeNode, primaryjoin=trees.c.root_node_id==trees.c.node_id, remote_side=trees.c.node_id, lazy=None),
+ children=relation(TreeNode,
+ primaryjoin=trees.c.parent_node_id==trees.c.node_id,
+ lazy=None,
+ cascade="all",
+ collection_class=mapped_collection(lambda n:n.name),
+ backref=backref('parent', primaryjoin=trees.c.parent_node_id==trees.c.node_id, remote_side=trees.c.node_id)
+ ),
+ data=relation(TreeData, cascade="all, delete-orphan", lazy=False)
), extension = TreeLoader())
+mapper(TreeData, treedata, properties={'id':treedata.c.data_id})
session = create_session()
node.children['node4'].append('subnode3')
node.children['node4'].append('subnode4')
node.children['node4'].children['subnode3'].append('subsubnode1')
+
+session.delete(node.children['node1'])
del node.children['node1']
print "\n\n\n----------------------------"
+++ /dev/null
-from sqlalchemy import *
-
-metadata = BoundMetaData('sqlite:///', echo=True)
-
-class Tree(object):
- def __init__(self, name='', father=None):
- self.name = name
- self.father = father
- def __str__(self):
- return '<TreeNode: %s>' % self.name
- def __repr__(self):
- return self.__str__()
-
-table = Table('tree', metadata,
- Column('id', Integer, primary_key=True),
- Column('name', String(64), nullable=False),
- Column('father_id', Integer, ForeignKey('tree.id'), nullable=True))
-table.create()
-
-mapper(Tree, table,
- properties={
- 'childs':relation(Tree, remote_side=table.c.father_id, primaryjoin=table.c.father_id==table.c.id, backref=backref('father', remote_side=table.c.id))},
- )
-
-root = Tree('root')
-child1 = Tree('child1', root)
-child2 = Tree('child2', root)
-child3 = Tree('child3', child1)
-
-child4 = Tree('child4')
-child1.childs.append(child4)
-
-session = create_session()
-session.save(root)
-session.flush()
-
-print root.childs
-print child1.childs
-print child2.childs
-print child2.father
-print child3.father