77# Distributed under terms of the MIT license.
88
99
10- from sqlalchemy import create_engine
10+ from sqlalchemy import create_engine , event
1111from sqlalchemy .exc import IntegrityError
1212from sqlalchemy .orm import sessionmaker
1313
@@ -103,6 +103,18 @@ class TreeTestingMixin(object):
103103 base = None
104104 model = None
105105
106+ def catch_queries (self , conn , cursor , statement , * args ):
107+ self .stmts .append (statement )
108+
109+ def start_query_counter (self ):
110+ self .stmts = []
111+ event .listen (self .session .bind .engine , "before_cursor_execute" ,
112+ self .catch_queries )
113+
114+ def stop_query_counter (self ):
115+ event .remove (self .session .bind .engine , "before_cursor_execute" ,
116+ self .catch_queries )
117+
106118 def setUp (self ):
107119 self .engine = create_engine ('sqlite:///:memory:' )
108120 Session = mptt_sessionmaker (sessionmaker (bind = self .engine ))
@@ -754,7 +766,7 @@ def test_move_tree_to_another_tree(self):
754766 | |
755767 6 26(20)27 30(22)31
756768
757- """
769+ """ # noqa
758770 node = self .session .query (self .model ).\
759771 filter (self .model .ppk == 12 ).one ()
760772 node .parent_id = 7
@@ -928,7 +940,8 @@ def test_move_to_toplevel_where_much_trees_from_right_side(self):
928940 4 8(20)9 12(22)13
929941
930942 """
931- node = self .session .query (self .model ).filter (self .model .ppk == 15 ).one ()
943+ node = self .session .query (self .model )\
944+ .filter (self .model .ppk == 15 ).one ()
932945 node .move_after ("1" )
933946 # id lft rgt lvl parent tree
934947 self .assertEqual ([(1 , 1 , 22 , 1 , None , 1 ),
@@ -957,7 +970,8 @@ def test_move_to_toplevel_where_much_trees_from_right_side(self):
957970 (21 , 11 , 14 , 3 , 18 , 3 ),
958971 (22 , 12 , 13 , 4 , 21 , 3 )], self .result .all ())
959972
960- node = self .session .query (self .model ).filter (self .model .ppk == 20 ).one ()
973+ node = self .session .query (self .model )\
974+ .filter (self .model .ppk == 20 ).one ()
961975 node .move_after ("1" )
962976 """ level tree_id = 1
963977 1 1(1)22
@@ -1254,11 +1268,55 @@ def test_get_tree(self):
12541268 tree = Tree.get_tree(self.session)
12551269 """
12561270 tree = self .model .get_tree (self .session )
1271+ tree_reqursively = self .model .get_tree_reqursively (self .session )
12571272
12581273 def go (id ):
12591274 return get_obj (self .session , self .model , id )
1260- self .assertEqual (tree ,
1261- [{'node' : go (1 ), 'children' : [{'node' : go (2 ), 'children' : [{'node' : go (3 )}]}, {'node' : go (4 ), 'children' : [{'node' : go (5 )}, {'node' : go (6 )}]}, {'node' : go (7 ), 'children' : [{'node' : go (8 ), 'children' : [{'node' : go (9 )}]}, {'node' : go (10 ), 'children' : [{'node' : go (11 )}]}]}]}, {'node' : go (12 ), 'children' : [{'node' : go (13 ), 'children' : [{'node' : go (14 )}]}, {'node' : go (15 ), 'children' : [{'node' : go (16 )}, {'node' : go (17 )}]}, {'node' : go (18 ), 'children' : [{'node' : go (19 ), 'children' : [{'node' : go (20 )}]}, {'node' : go (21 ), 'children' : [{'node' : go (22 )}]}]}]}])
1275+
1276+ reference_tree = [{'node' : go (1 ), 'children' : [{'node' : go (2 ), 'children' : [{'node' : go (3 )}]}, {'node' : go (4 ), 'children' : [{'node' : go (5 )}, {'node' : go (6 )}]}, {'node' : go (7 ), 'children' : [{'node' : go (8 ), 'children' : [{'node' : go (9 )}]}, {'node' : go (10 ), 'children' : [{'node' : go (11 )}]}]}]}, {'node' : go (12 ), 'children' : [{'node' : go (13 ), 'children' : [{'node' : go (14 )}]}, {'node' : go (15 ), 'children' : [{'node' : go (16 )}, {'node' : go (17 )}]}, {'node' : go (18 ), 'children' : [{'node' : go (19 ), 'children' : [{'node' : go (20 )}]}, {'node' : go (21 ), 'children' : [{'node' : go (22 )}]}]}]}] # noqa
1277+
1278+ self .assertEqual (tree , reference_tree )
1279+ self .assertEqual (tree_reqursively , reference_tree )
1280+
1281+ def test_get_tree_count_query (self ):
1282+ """
1283+ Count num of queries to the database.
1284+ See https://github.com/ITCase/sqlalchemy_mptt/issues/39
1285+
1286+
1287+ Use ``--nocapture`` option for show run time:
1288+
1289+ ::
1290+
1291+ nosetests sqlalchemy_mptt.tests.test_events:TestTree.test_get_tree_count_query --nocapture
1292+ Get tree: 0:00:00.001817
1293+ Get tree reqursively: 0:00:00.020615
1294+ .
1295+ ----------------------------------------------------------------------
1296+ Ran 1 test in 0.064s
1297+
1298+ OK
1299+ """ # noqa
1300+ from datetime import datetime
1301+ self .session .commit ()
1302+
1303+ # Get tree by for cycle
1304+ self .start_query_counter ()
1305+ self .assertEqual (0 , len (self .stmts ))
1306+ startTime = datetime .now ()
1307+ self .model .get_tree (self .session )
1308+ print ("Get tree: {!s:>26}" .format (datetime .now () - startTime ))
1309+ self .assertEqual (1 , len (self .stmts ))
1310+ self .stop_query_counter ()
1311+
1312+ # Get tree by recursion
1313+ self .start_query_counter ()
1314+ self .assertEqual (0 , len (self .stmts ))
1315+ startTime = datetime .now ()
1316+ self .model .get_tree_reqursively (self .session )
1317+ print ("Get tree reqursively: {}" .format (datetime .now () - startTime ))
1318+ self .assertEqual (23 , len (self .stmts ))
1319+ self .stop_query_counter ()
12621320
12631321 def test_get_json_tree (self ):
12641322 """.. note::
@@ -1271,9 +1329,13 @@ def test_get_json_tree(self):
12711329
12721330 tree = Tree.get_tree(self.session, json=True)
12731331 """
1332+ reference_tree = [{'children' : [{'children' : [{'id' : 3 , 'label' : '<Node (3)>' }], 'id' : 2 , 'label' : '<Node (2)>' }, {'children' : [{'id' : 5 , 'label' : '<Node (5)>' }, {'id' : 6 , 'label' : '<Node (6)>' }], 'id' : 4 , 'label' : '<Node (4)>' }, {'children' : [{'children' : [{'id' : 9 , 'label' : '<Node (9)>' }], 'id' : 8 , 'label' : '<Node (8)>' }, {'children' : [{'id' : 11 , 'label' : '<Node (11)>' }], 'id' : 10 , 'label' : '<Node (10)>' }], 'id' : 7 , 'label' : '<Node (7)>' }], 'id' : 1 , 'label' : '<Node (1)>' }, {'children' : [{'children' : [{'id' : 14 , 'label' : '<Node (14)>' }], 'id' : 13 , 'label' : '<Node (13)>' }, {'children' : [{'id' : 16 , 'label' : '<Node (16)>' }, {'id' : 17 , 'label' : '<Node (17)>' }], 'id' : 15 , 'label' : '<Node (15)>' }, {'children' : [{'children' : [{'id' : 20 , 'label' : '<Node (20)>' }], 'id' : 19 , 'label' : '<Node (19)>' }, {'children' : [{'id' : 22 , 'label' : '<Node (22)>' }], 'id' : 21 , 'label' : '<Node (21)>' }], 'id' : 18 , 'label' : '<Node (18)>' }], 'id' : 12 , 'label' : '<Node (12)>' }] # noqa
1333+
12741334 tree = self .model .get_tree (self .session , json = True )
1275- self .assertEqual (tree , [{'children' : [{'children' : [{'id' : 3 , 'label' : '<Node (3)>' }], 'id' : 2 , 'label' : '<Node (2)>' }, {'children' : [{'id' : 5 , 'label' : '<Node (5)>' }, {'id' : 6 , 'label' : '<Node (6)>' }], 'id' : 4 , 'label' : '<Node (4)>' }, {'children' : [{'children' : [{'id' : 9 , 'label' : '<Node (9)>' }], 'id' : 8 , 'label' : '<Node (8)>' }, {'children' : [{'id' : 11 , 'label' : '<Node (11)>' }], 'id' : 10 , 'label' : '<Node (10)>' }], 'id' : 7 , 'label' : '<Node (7)>' }], 'id' : 1 , 'label' : '<Node (1)>' }, {
1276- 'children' : [{'children' : [{'id' : 14 , 'label' : '<Node (14)>' }], 'id' : 13 , 'label' : '<Node (13)>' }, {'children' : [{'id' : 16 , 'label' : '<Node (16)>' }, {'id' : 17 , 'label' : '<Node (17)>' }], 'id' : 15 , 'label' : '<Node (15)>' }, {'children' : [{'children' : [{'id' : 20 , 'label' : '<Node (20)>' }], 'id' : 19 , 'label' : '<Node (19)>' }, {'children' : [{'id' : 22 , 'label' : '<Node (22)>' }], 'id' : 21 , 'label' : '<Node (21)>' }], 'id' : 18 , 'label' : '<Node (18)>' }], 'id' : 12 , 'label' : '<Node (12)>' }])
1335+ tree_reqursively = self .model .get_tree_reqursively (self .session ,
1336+ json = True )
1337+ self .assertEqual (tree , reference_tree )
1338+ self .assertEqual (tree_reqursively , reference_tree )
12771339
12781340 def test_get_json_tree_with_custom_field (self ):
12791341 """.. note::
@@ -1292,9 +1354,14 @@ def fields(node):
12921354 """
12931355 def fields (node ):
12941356 return {'visible' : node .visible }
1357+
1358+ reference_tree = [{'visible' : None , 'children' : [{'visible' : True , 'children' : [{'visible' : True , 'id' : 3 , 'label' : '<Node (3)>' }], 'id' : 2 , 'label' : '<Node (2)>' }, {'visible' : True , 'children' : [{'visible' : True , 'id' : 5 , 'label' : '<Node (5)>' }, {'visible' : True , 'id' : 6 , 'label' : '<Node (6)>' }], 'id' : 4 , 'label' : '<Node (4)>' }, {'visible' : True , 'children' : [{'visible' : True , 'children' : [{'visible' : None , 'id' : 9 , 'label' : '<Node (9)>' }], 'id' : 8 , 'label' : '<Node (8)>' }, {'visible' : None , 'children' : [{'visible' : None , 'id' : 11 , 'label' : '<Node (11)>' }], 'id' : 10 , 'label' : '<Node (10)>' }], 'id' : 7 , 'label' : '<Node (7)>' }], 'id' : 1 , 'label' : '<Node (1)>' }, {'visible' : None , 'children' : [{'visible' : None , 'children' : [{'visible' : None , 'id' : 14 , 'label' : '<Node (14)>' }], 'id' : 13 , 'label' : '<Node (13)>' }, {'visible' : None , 'children' : [{'visible' : None , 'id' : 16 , 'label' : '<Node (16)>' }, {'visible' : None , 'id' : 17 , 'label' : '<Node (17)>' }], 'id' : 15 , 'label' : '<Node (15)>' }, {'visible' : None , 'children' : [{'visible' : None , 'children' : [{'visible' : None , 'id' : 20 , 'label' : '<Node (20)>' }], 'id' : 19 , 'label' : '<Node (19)>' }, {'visible' : None , 'children' : [{'visible' : None , 'id' : 22 , 'label' : '<Node (22)>' }], 'id' : 21 , 'label' : '<Node (21)>' }], 'id' : 18 , 'label' : '<Node (18)>' }], 'id' : 12 , 'label' : '<Node (12)>' }] # noqa
1359+
12951360 tree = self .model .get_tree (self .session , json = True , json_fields = fields )
1296- self .assertEqual (tree , [{'visible' : None , 'children' : [{'visible' : True , 'children' : [{'visible' : True , 'id' : 3 , 'label' : '<Node (3)>' }], 'id' : 2 , 'label' : '<Node (2)>' }, {'visible' : True , 'children' : [{'visible' : True , 'id' : 5 , 'label' : '<Node (5)>' }, {'visible' : True , 'id' : 6 , 'label' : '<Node (6)>' }], 'id' : 4 , 'label' : '<Node (4)>' }, {'visible' : True , 'children' : [{'visible' : True , 'children' : [{'visible' : None , 'id' : 9 , 'label' : '<Node (9)>' }], 'id' : 8 , 'label' : '<Node (8)>' }, {'visible' : None , 'children' : [{'visible' : None , 'id' : 11 , 'label' : '<Node (11)>' }], 'id' : 10 , 'label' : '<Node (10)>' }], 'id' : 7 , 'label' : '<Node (7)>' }], 'id' : 1 , 'label' : '<Node (1)>' }, {
1297- 'visible' : None , 'children' : [{'visible' : None , 'children' : [{'visible' : None , 'id' : 14 , 'label' : '<Node (14)>' }], 'id' : 13 , 'label' : '<Node (13)>' }, {'visible' : None , 'children' : [{'visible' : None , 'id' : 16 , 'label' : '<Node (16)>' }, {'visible' : None , 'id' : 17 , 'label' : '<Node (17)>' }], 'id' : 15 , 'label' : '<Node (15)>' }, {'visible' : None , 'children' : [{'visible' : None , 'children' : [{'visible' : None , 'id' : 20 , 'label' : '<Node (20)>' }], 'id' : 19 , 'label' : '<Node (19)>' }, {'visible' : None , 'children' : [{'visible' : None , 'id' : 22 , 'label' : '<Node (22)>' }], 'id' : 21 , 'label' : '<Node (21)>' }], 'id' : 18 , 'label' : '<Node (18)>' }], 'id' : 12 , 'label' : '<Node (12)>' }])
1361+ tree_reqursively = self .model .get_tree (self .session , json = True ,
1362+ json_fields = fields )
1363+ self .assertEqual (tree , reference_tree )
1364+ self .assertEqual (tree_reqursively , reference_tree )
12981365
12991366 def test_rebuild (self ):
13001367 """ Rebuild tree with tree_id==1
0 commit comments