diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2013-04-27 17:21:31 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2013-04-27 17:21:31 -0400 |
| commit | 8cdb4543bd7a85bef0286433576aafe0fb8e7c4c (patch) | |
| tree | 4f69b10e11a0cb6e58f0bab326a534b7dbcd12f8 /examples/nested_sets | |
| parent | 5f51d409ccda1033a41256dfc28e46bc6923521d (diff) | |
| download | sqlalchemy-8cdb4543bd7a85bef0286433576aafe0fb8e7c4c.tar.gz | |
modernize some more examples
Diffstat (limited to 'examples/nested_sets')
| -rw-r--r-- | examples/nested_sets/nested_sets.py | 98 |
1 files changed, 53 insertions, 45 deletions
diff --git a/examples/nested_sets/nested_sets.py b/examples/nested_sets/nested_sets.py index e35ea61c3..8225a09f2 100644 --- a/examples/nested_sets/nested_sets.py +++ b/examples/nested_sets/nested_sets.py @@ -6,47 +6,17 @@ http://www.intelligententerprise.com/001020/celko.jhtml from sqlalchemy import (create_engine, Column, Integer, String, select, case, func) -from sqlalchemy.orm import sessionmaker, MapperExtension, aliased +from sqlalchemy.orm import Session, aliased from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy import event -engine = create_engine('sqlite://', echo=True) Base = declarative_base() -class NestedSetExtension(MapperExtension): - def before_insert(self, mapper, connection, instance): - if not instance.parent: - instance.left = 1 - instance.right = 2 - else: - personnel = mapper.mapped_table - right_most_sibling = connection.scalar( - select([personnel.c.rgt]).where(personnel.c.emp==instance.parent.emp) - ) - - connection.execute( - personnel.update(personnel.c.rgt>=right_most_sibling).values( - lft = case( - [(personnel.c.lft>right_most_sibling, personnel.c.lft + 2)], - else_ = personnel.c.lft - ), - rgt = case( - [(personnel.c.rgt>=right_most_sibling, personnel.c.rgt + 2)], - else_ = personnel.c.rgt - ) - ) - ) - instance.left = right_most_sibling - instance.right = right_most_sibling + 1 - - # before_update() would be needed to support moving of nodes - # after_delete() would be needed to support removal of nodes. - # [ticket:1172] needs to be implemented for deletion to work as well. - class Employee(Base): __tablename__ = 'personnel' __mapper_args__ = { - 'extension':NestedSetExtension(), - 'batch':False # allows extension to fire for each instance before going to the next. + 'batch': False # allows extension to fire for each + # instance before going to the next. } parent = None @@ -59,9 +29,44 @@ class Employee(Base): def __repr__(self): return "Employee(%s, %d, %d)" % (self.emp, self.left, self.right) +@event.listens_for(Employee, "before_insert") +def before_insert(mapper, connection, instance): + if not instance.parent: + instance.left = 1 + instance.right = 2 + else: + personnel = mapper.mapped_table + right_most_sibling = connection.scalar( + select([personnel.c.rgt]). + where(personnel.c.emp == instance.parent.emp) + ) + + connection.execute( + personnel.update( + personnel.c.rgt >= right_most_sibling).values( + lft=case( + [(personnel.c.lft > right_most_sibling, + personnel.c.lft + 2)], + else_=personnel.c.lft + ), + rgt=case( + [(personnel.c.rgt >= right_most_sibling, + personnel.c.rgt + 2)], + else_=personnel.c.rgt + ) + ) + ) + instance.left = right_most_sibling + instance.right = right_most_sibling + 1 + + # before_update() would be needed to support moving of nodes + # after_delete() would be needed to support removal of nodes. + +engine = create_engine('sqlite://', echo=True) + Base.metadata.create_all(engine) -session = sessionmaker(bind=engine)() +session = Session(bind=engine) albert = Employee(emp='Albert') bert = Employee(emp='Bert') @@ -81,23 +86,26 @@ fred.parent = chuck session.add_all([albert, bert, chuck, donna, eddie, fred]) session.commit() -print session.query(Employee).all() +print(session.query(Employee).all()) # 1. Find an employee and all his/her supervisors, no matter how deep the tree. ealias = aliased(Employee) -print session.query(Employee).\ +print(session.query(Employee).\ filter(ealias.left.between(Employee.left, Employee.right)).\ - filter(ealias.emp=='Eddie').all() + filter(ealias.emp == 'Eddie').all()) -#2. Find the employee and all his/her subordinates. (This query has a nice symmetry with the first query.) -print session.query(Employee).\ +#2. Find the employee and all his/her subordinates. +# (This query has a nice symmetry with the first query.) +print(session.query(Employee).\ filter(Employee.left.between(ealias.left, ealias.right)).\ - filter(ealias.emp=='Chuck').all() + filter(ealias.emp == 'Chuck').all()) -#3. Find the level of each node, so you can print the tree as an indented listing. -for indentation, employee in session.query(func.count(Employee.emp).label('indentation') - 1, ealias).\ +#3. Find the level of each node, so you can print the tree +# as an indented listing. +for indentation, employee in session.query( + func.count(Employee.emp).label('indentation') - 1, ealias).\ filter(ealias.left.between(Employee.left, Employee.right)).\ group_by(ealias.emp).\ - order_by(ealias.left): - print " " * indentation + str(employee) + order_by(ealias.left): + print(" " * indentation + str(employee)) |
