mirror of
https://github.com/sqlalchemy/sqlalchemy.git
synced 2026-06-01 05:18:44 -04:00
c6bceb7775
- converted all eager to joined in examples - fixed beaker/advanced.py to reference RelationshipCache
134 lines
4.0 KiB
Python
134 lines
4.0 KiB
Python
from sqlalchemy import MetaData, Table, Column, Sequence, ForeignKey,\
|
|
Integer, String, create_engine
|
|
|
|
from sqlalchemy.orm import sessionmaker, mapper, relationship, backref,\
|
|
joinedload_all
|
|
|
|
from sqlalchemy.orm.collections import attribute_mapped_collection
|
|
|
|
metadata = MetaData()
|
|
|
|
tree_table = Table('tree', metadata,
|
|
Column('id', Integer, primary_key=True),
|
|
Column('parent_id', Integer, ForeignKey('tree.id')),
|
|
Column('name', String(50), nullable=False)
|
|
)
|
|
|
|
class TreeNode(object):
|
|
def __init__(self, name, parent=None):
|
|
self.name = name
|
|
self.parent = parent
|
|
|
|
def append(self, nodename):
|
|
self.children[nodename] = TreeNode(nodename, parent=self)
|
|
|
|
def __repr__(self):
|
|
return "TreeNode(name=%r, id=%r, parent_id=%r)" % (
|
|
self.name,
|
|
self.id,
|
|
self.parent_id
|
|
)
|
|
|
|
def dump_tree(node, indent=0):
|
|
|
|
return " " * indent + repr(node) + \
|
|
"\n" + \
|
|
"".join([
|
|
dump_tree(c, indent +1)
|
|
for c in node.children.values()]
|
|
)
|
|
|
|
|
|
mapper(TreeNode, tree_table, properties={
|
|
'children': relationship(TreeNode,
|
|
|
|
# cascade deletions
|
|
cascade="all",
|
|
|
|
# many to one + adjacency list - remote_side
|
|
# is required to reference the 'remote'
|
|
# column in the join condition.
|
|
backref=backref("parent", remote_side=tree_table.c.id),
|
|
|
|
# children will be represented as a dictionary
|
|
# on the "name" attribute.
|
|
collection_class=attribute_mapped_collection('name'),
|
|
)
|
|
})
|
|
|
|
if __name__ == '__main__':
|
|
engine = create_engine('sqlite://', echo=True)
|
|
|
|
def msg(msg):
|
|
print "\n\n\n" + "-" * len(msg)
|
|
print msg
|
|
print "-" * len(msg)
|
|
|
|
msg("Creating Tree Table:")
|
|
|
|
metadata.create_all(engine)
|
|
|
|
# session. using expire_on_commit=False
|
|
# so that the session's contents are not expired
|
|
# after each transaction commit.
|
|
session = sessionmaker(engine, expire_on_commit=False)()
|
|
|
|
node = TreeNode('rootnode')
|
|
node.append('node1')
|
|
node.append('node3')
|
|
|
|
node2 = TreeNode('node2')
|
|
node2.append('subnode1')
|
|
node.children['node2'] = node2
|
|
node.children['node2'].append('subnode2')
|
|
|
|
msg("Created new tree structure:")
|
|
|
|
print dump_tree(node)
|
|
|
|
msg("flush + commit:")
|
|
|
|
session.add(node)
|
|
session.commit()
|
|
|
|
msg("Tree After Save:")
|
|
|
|
print dump_tree(node)
|
|
|
|
node.append('node4')
|
|
node.children['node4'].append('subnode3')
|
|
node.children['node4'].append('subnode4')
|
|
node.children['node4'].children['subnode3'].append('subsubnode1')
|
|
|
|
# mark node1 as deleted and remove
|
|
session.delete(node.children['node1'])
|
|
|
|
msg("Removed node1. flush + commit:")
|
|
session.commit()
|
|
|
|
print "\n\n\n----------------------------"
|
|
print "Tree After Save:"
|
|
print "----------------------------"
|
|
|
|
# expire the "children" collection so that
|
|
# it reflects the deletion of "node1".
|
|
session.expire(node, ['children'])
|
|
print dump_tree(node)
|
|
|
|
msg("Emptying out the session entirely, "
|
|
"selecting tree on root, using eager loading to join four levels deep.")
|
|
session.expunge_all()
|
|
node = session.query(TreeNode).\
|
|
options(joinedload_all("children", "children",
|
|
"children", "children")).\
|
|
filter(TreeNode.name=="rootnode").\
|
|
first()
|
|
|
|
msg("Full Tree:")
|
|
print dump_tree(node)
|
|
|
|
msg( "Marking root node as deleted, flush + commit:" )
|
|
|
|
session.delete(node)
|
|
session.commit()
|