📄 eager_relations.py
字号:
mapper(User, users, properties={ 'addresses':relation(Address, lazy=False), 'orders':relation(Order, lazy=False) }) mapper(Address, addresses) mapper(Order, orders) allusers = create_session().query(User).all() # using a textual select, the columns will be 'id' and 'name'. # the eager loaders have aliases which should not hit on those columns, they should # be required to locate only their aliased/fully table qualified column name. noeagers = create_session().query(User).from_statement("select * from users").all() assert 'orders' not in noeagers[0].__dict__ assert 'addresses' not in noeagers[0].__dict__ @testing.fails_on('maxdb') def test_limit(self): """test limit operations combined with lazy-load relationships.""" mapper(Item, items) mapper(Order, orders, properties={ 'items':relation(Item, secondary=order_items, lazy=False, order_by=items.c.id) }) mapper(User, users, properties={ 'addresses':relation(mapper(Address, addresses), lazy=False, order_by=addresses.c.id), 'orders':relation(Order, lazy=True) }) sess = create_session() q = sess.query(User) if testing.against('mysql'): l = q.limit(2).all() assert fixtures.user_all_result[:2] == l else: l = q.limit(2).offset(1).order_by(User.id).all() print fixtures.user_all_result[1:3] print l assert fixtures.user_all_result[1:3] == l def test_distinct(self): # this is an involved 3x union of the users table to get a lot of rows. # then see if the "distinct" works its way out. you actually get the same # result with or without the distinct, just via less or more rows. u2 = users.alias('u2') s = union_all(u2.select(use_labels=True), u2.select(use_labels=True), u2.select(use_labels=True)).alias('u') mapper(User, users, properties={ 'addresses':relation(mapper(Address, addresses), lazy=False), }) sess = create_session() q = sess.query(User) def go(): l = q.filter(s.c.u2_id==User.c.id).distinct().all() assert fixtures.user_address_result == l self.assert_sql_count(testing.db, go, 1) @testing.fails_on('maxdb') def test_limit_2(self): mapper(Keyword, keywords) mapper(Item, items, properties = dict( keywords = relation(Keyword, secondary=item_keywords, lazy=False, order_by=[keywords.c.id]), )) sess = create_session() q = sess.query(Item) l = q.filter((Item.c.description=='item 2') | (Item.c.description=='item 5') | (Item.c.description=='item 3')).\ order_by(Item.id).limit(2).all() assert fixtures.item_keyword_result[1:3] == l @testing.fails_on('maxdb') def test_limit_3(self): """test that the ORDER BY is propigated from the inner select to the outer select, when using the 'wrapped' select statement resulting from the combination of eager loading and limit/offset clauses.""" mapper(Item, items) mapper(Order, orders, properties = dict( items = relation(Item, secondary=order_items, lazy=False) )) mapper(Address, addresses) mapper(User, users, properties = dict( addresses = relation(Address, lazy=False), orders = relation(Order, lazy=False), )) sess = create_session() q = sess.query(User) if not testing.against('maxdb', 'mssql'): l = q.join('orders').order_by(Order.user_id.desc()).limit(2).offset(1) assert [ User(id=9, orders=[Order(id=2), Order(id=4)], addresses=[Address(id=5)] ), User(id=7, orders=[Order(id=1), Order(id=3), Order(id=5)], addresses=[Address(id=1)] ) ] == l.all() l = q.join('addresses').order_by(Address.email_address.desc()).limit(1).offset(0) assert [ User(id=7, orders=[Order(id=1), Order(id=3), Order(id=5)], addresses=[Address(id=1)] ) ] == l.all() def test_limit_4(self): # tests the LIMIT/OFFSET aliasing on a mapper against a select. original issue from ticket #904 sel = select([users, addresses.c.email_address], users.c.id==addresses.c.user_id).alias('useralias') mapper(User, sel, properties={ 'orders':relation(Order, primaryjoin=sel.c.id==orders.c.user_id, lazy=False) }) mapper(Order, orders) sess = create_session() self.assertEquals(sess.query(User).first(), User(name=u'jack',orders=[ Order(address_id=1,description=u'order 1',isopen=0,user_id=7,id=1), Order(address_id=1,description=u'order 3',isopen=1,user_id=7,id=3), Order(address_id=None,description=u'order 5',isopen=0,user_id=7,id=5)], email_address=u'jack@bean.com',id=7) ) def test_one_to_many_scalar(self): mapper(User, users, properties = dict( address = relation(mapper(Address, addresses), lazy=False, uselist=False) )) q = create_session().query(User) def go(): l = q.filter(users.c.id == 7).all() assert [User(id=7, address=Address(id=1))] == l self.assert_sql_count(testing.db, go, 1) @testing.fails_on('maxdb') def test_many_to_one(self): mapper(Address, addresses, properties = dict( user = relation(mapper(User, users), lazy=False) )) sess = create_session() q = sess.query(Address) def go(): a = q.filter(addresses.c.id==1).one() assert a.user is not None u1 = sess.query(User).get(7) assert a.user is u1 self.assert_sql_count(testing.db, go, 1) def test_one_and_many(self): """tests eager load for a parent object with a child object that contains a many-to-many relationship to a third object.""" mapper(User, users, properties={ 'orders':relation(Order, lazy=False) }) mapper(Item, items) mapper(Order, orders, properties = dict( items = relation(Item, secondary=order_items, lazy=False, order_by=items.c.id) )) q = create_session().query(User) l = q.filter("users.id in (7, 8, 9)") def go(): assert fixtures.user_order_result[0:3] == l.all() self.assert_sql_count(testing.db, go, 1) def test_double_with_aggregate(self): max_orders_by_user = select([func.max(orders.c.id).label('order_id')], group_by=[orders.c.user_id]).alias('max_orders_by_user') max_orders = orders.select(orders.c.id==max_orders_by_user.c.order_id).alias('max_orders') mapper(Order, orders) mapper(User, users, properties={ 'orders':relation(Order, backref='user', lazy=False), 'max_order':relation(mapper(Order, max_orders, non_primary=True), lazy=False, uselist=False) }) q = create_session().query(User) def go(): assert [ User(id=7, orders=[ Order(id=1), Order(id=3), Order(id=5), ], max_order=Order(id=5) ), User(id=8, orders=[]), User(id=9, orders=[Order(id=2),Order(id=4)], max_order=Order(id=4) ), User(id=10), ] == q.all() self.assert_sql_count(testing.db, go, 1) def test_wide(self): mapper(Order, orders, properties={'items':relation(Item, secondary=order_items, lazy=False, order_by=items.c.id)}) mapper(Item, items) mapper(User, users, properties = dict( addresses = relation(mapper(Address, addresses), lazy = False), orders = relation(Order, lazy = False), )) q = create_session().query(User) l = q.all() assert fixtures.user_all_result == q.all() def test_against_select(self): """test eager loading of a mapper which is against a select""" s = select([orders], orders.c.isopen==1).alias('openorders') mapper(Order, s, properties={ 'user':relation(User, lazy=False) }) mapper(User, users) mapper(Item, items) q = create_session().query(Order) assert [ Order(id=3, user=User(id=7)), Order(id=4, user=User(id=9)) ] == q.all() q = q.select_from(s.join(order_items).join(items)).filter(~Item.id.in_([1, 2, 5])) assert [ Order(id=3, user=User(id=7)), ] == q.all() def test_aliasing(self): """test that eager loading uses aliases to insulate the eager load from regular criterion against those tables.""" mapper(User, users, properties = dict( addresses = relation(mapper(Address, addresses), lazy=False) )) q = create_session().query(User) l = q.filter(addresses.c.email_address == 'ed@lala.com').filter(Address.user_id==User.id) assert fixtures.user_address_result[1:2] == l.all()class AddEntityTest(FixtureTest): keep_mappers = False keep_data = True def _assert_result(self): return [ ( User(id=7, addresses=[Address(id=1)] ), Order(id=1, items=[Item(id=1), Item(id=2), Item(id=3)] ), ), ( User(id=7, addresses=[Address(id=1)] ), Order(id=3, items=[Item(id=3), Item(id=4), Item(id=5)] ), ), ( User(id=7, addresses=[Address(id=1)] ), Order(id=5, items=[Item(id=5)] ), ), ( User(id=9, addresses=[Address(id=5)] ), Order(id=2, items=[Item(id=1), Item(id=2), Item(id=3)] ), ), ( User(id=9, addresses=[Address(id=5)] ), Order(id=4, items=[Item(id=1), Item(id=5)] ), ) ] def test_basic(self): mapper(User, users, properties={ 'addresses':relation(Address, lazy=False), 'orders':relation(Order) }) mapper(Address, addresses) mapper(Order, orders, properties={ 'items':relation(Item, secondary=order_items, lazy=False, order_by=items.c.id) })
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -