/test/orm/inheritance/test_manytomany.py

https://bitbucket.org/zzzeek/sqlalchemy · Python · 374 lines · 312 code · 54 blank · 8 comment · 6 complexity · f54608b25114f223e8cf6d0a3f577570 MD5 · raw file

  1. from sqlalchemy import Column
  2. from sqlalchemy import ForeignKey
  3. from sqlalchemy import Integer
  4. from sqlalchemy import Sequence
  5. from sqlalchemy import String
  6. from sqlalchemy import Table
  7. from sqlalchemy.orm import class_mapper
  8. from sqlalchemy.orm import relationship
  9. from sqlalchemy.testing import eq_
  10. from sqlalchemy.testing import fixtures
  11. from sqlalchemy.testing.fixtures import fixture_session
  12. class InheritTest(fixtures.MappedTest):
  13. """deals with inheritance and many-to-many relationships"""
  14. @classmethod
  15. def define_tables(cls, metadata):
  16. global principals
  17. global users
  18. global groups
  19. global user_group_map
  20. principals = Table(
  21. "principals",
  22. metadata,
  23. Column(
  24. "principal_id",
  25. Integer,
  26. Sequence("principal_id_seq", optional=False),
  27. primary_key=True,
  28. ),
  29. Column("name", String(50), nullable=False),
  30. )
  31. users = Table(
  32. "prin_users",
  33. metadata,
  34. Column(
  35. "principal_id",
  36. Integer,
  37. ForeignKey("principals.principal_id"),
  38. primary_key=True,
  39. ),
  40. Column("password", String(50), nullable=False),
  41. Column("email", String(50), nullable=False),
  42. Column("login_id", String(50), nullable=False),
  43. )
  44. groups = Table(
  45. "prin_groups",
  46. metadata,
  47. Column(
  48. "principal_id",
  49. Integer,
  50. ForeignKey("principals.principal_id"),
  51. primary_key=True,
  52. ),
  53. )
  54. user_group_map = Table(
  55. "prin_user_group_map",
  56. metadata,
  57. Column(
  58. "user_id",
  59. Integer,
  60. ForeignKey("prin_users.principal_id"),
  61. primary_key=True,
  62. ),
  63. Column(
  64. "group_id",
  65. Integer,
  66. ForeignKey("prin_groups.principal_id"),
  67. primary_key=True,
  68. ),
  69. )
  70. def test_basic(self):
  71. class Principal(object):
  72. def __init__(self, **kwargs):
  73. for key, value in kwargs.items():
  74. setattr(self, key, value)
  75. class User(Principal):
  76. pass
  77. class Group(Principal):
  78. pass
  79. self.mapper_registry.map_imperatively(Principal, principals)
  80. self.mapper_registry.map_imperatively(User, users, inherits=Principal)
  81. self.mapper_registry.map_imperatively(
  82. Group,
  83. groups,
  84. inherits=Principal,
  85. properties={
  86. "users": relationship(
  87. User,
  88. secondary=user_group_map,
  89. lazy="select",
  90. backref="groups",
  91. )
  92. },
  93. )
  94. g = Group(name="group1")
  95. g.users.append(
  96. User(
  97. name="user1",
  98. password="pw",
  99. email="foo@bar.com",
  100. login_id="lg1",
  101. )
  102. )
  103. sess = fixture_session()
  104. sess.add(g)
  105. sess.flush()
  106. # TODO: put an assertion
  107. class InheritTest2(fixtures.MappedTest):
  108. """deals with inheritance and many-to-many relationships"""
  109. @classmethod
  110. def define_tables(cls, metadata):
  111. global foo, bar, foo_bar
  112. foo = Table(
  113. "foo",
  114. metadata,
  115. Column(
  116. "id",
  117. Integer,
  118. Sequence("foo_id_seq", optional=True),
  119. primary_key=True,
  120. ),
  121. Column("data", String(20)),
  122. )
  123. bar = Table(
  124. "bar",
  125. metadata,
  126. Column("bid", Integer, ForeignKey("foo.id"), primary_key=True),
  127. )
  128. foo_bar = Table(
  129. "foo_bar",
  130. metadata,
  131. Column("foo_id", Integer, ForeignKey("foo.id")),
  132. Column("bar_id", Integer, ForeignKey("bar.bid")),
  133. )
  134. def test_get(self):
  135. class Foo(object):
  136. def __init__(self, data=None):
  137. self.data = data
  138. class Bar(Foo):
  139. pass
  140. self.mapper_registry.map_imperatively(Foo, foo)
  141. self.mapper_registry.map_imperatively(Bar, bar, inherits=Foo)
  142. print(foo.join(bar).primary_key)
  143. print(class_mapper(Bar).primary_key)
  144. b = Bar("somedata")
  145. sess = fixture_session()
  146. sess.add(b)
  147. sess.flush()
  148. sess.expunge_all()
  149. # test that "bar.bid" does not need to be referenced in a get
  150. # (ticket 185)
  151. assert sess.get(Bar, b.id).id == b.id
  152. def test_basic(self):
  153. class Foo(object):
  154. def __init__(self, data=None):
  155. self.data = data
  156. self.mapper_registry.map_imperatively(Foo, foo)
  157. class Bar(Foo):
  158. pass
  159. self.mapper_registry.map_imperatively(
  160. Bar,
  161. bar,
  162. inherits=Foo,
  163. properties={
  164. "foos": relationship(Foo, secondary=foo_bar, lazy="joined")
  165. },
  166. )
  167. sess = fixture_session()
  168. b = Bar("barfoo")
  169. sess.add(b)
  170. sess.flush()
  171. f1 = Foo("subfoo1")
  172. f2 = Foo("subfoo2")
  173. b.foos.append(f1)
  174. b.foos.append(f2)
  175. sess.flush()
  176. sess.expunge_all()
  177. result = sess.query(Bar).all()
  178. print(result[0])
  179. print(result[0].foos)
  180. self.assert_unordered_result(
  181. result,
  182. Bar,
  183. {
  184. "id": b.id,
  185. "data": "barfoo",
  186. "foos": (
  187. Foo,
  188. [
  189. {"id": f1.id, "data": "subfoo1"},
  190. {"id": f2.id, "data": "subfoo2"},
  191. ],
  192. ),
  193. },
  194. )
  195. class InheritTest3(fixtures.MappedTest):
  196. """deals with inheritance and many-to-many relationships"""
  197. @classmethod
  198. def define_tables(cls, metadata):
  199. global foo, bar, blub, bar_foo, blub_bar, blub_foo
  200. # the 'data' columns are to appease SQLite which cant handle a blank
  201. # INSERT
  202. foo = Table(
  203. "foo",
  204. metadata,
  205. Column(
  206. "id",
  207. Integer,
  208. Sequence("foo_seq", optional=True),
  209. primary_key=True,
  210. ),
  211. Column("data", String(20)),
  212. )
  213. bar = Table(
  214. "bar",
  215. metadata,
  216. Column("id", Integer, ForeignKey("foo.id"), primary_key=True),
  217. Column("bar_data", String(20)),
  218. )
  219. blub = Table(
  220. "blub",
  221. metadata,
  222. Column("id", Integer, ForeignKey("bar.id"), primary_key=True),
  223. Column("blub_data", String(20)),
  224. )
  225. bar_foo = Table(
  226. "bar_foo",
  227. metadata,
  228. Column("bar_id", Integer, ForeignKey("bar.id")),
  229. Column("foo_id", Integer, ForeignKey("foo.id")),
  230. )
  231. blub_bar = Table(
  232. "bar_blub",
  233. metadata,
  234. Column("blub_id", Integer, ForeignKey("blub.id")),
  235. Column("bar_id", Integer, ForeignKey("bar.id")),
  236. )
  237. blub_foo = Table(
  238. "blub_foo",
  239. metadata,
  240. Column("blub_id", Integer, ForeignKey("blub.id")),
  241. Column("foo_id", Integer, ForeignKey("foo.id")),
  242. )
  243. def test_basic(self):
  244. class Foo(object):
  245. def __init__(self, data=None):
  246. self.data = data
  247. def __repr__(self):
  248. return "Foo id %d, data %s" % (self.id, self.data)
  249. self.mapper_registry.map_imperatively(Foo, foo)
  250. class Bar(Foo):
  251. def __repr__(self):
  252. return "Bar id %d, data %s" % (self.id, self.data)
  253. self.mapper_registry.map_imperatively(
  254. Bar,
  255. bar,
  256. inherits=Foo,
  257. properties={
  258. "foos": relationship(Foo, secondary=bar_foo, lazy="select")
  259. },
  260. )
  261. sess = fixture_session()
  262. b = Bar("bar #1")
  263. sess.add(b)
  264. b.foos.append(Foo("foo #1"))
  265. b.foos.append(Foo("foo #2"))
  266. sess.flush()
  267. compare = [repr(b)] + sorted([repr(o) for o in b.foos])
  268. sess.expunge_all()
  269. result = sess.query(Bar).all()
  270. print(repr(result[0]) + repr(result[0].foos))
  271. found = [repr(result[0])] + sorted([repr(o) for o in result[0].foos])
  272. eq_(found, compare)
  273. def test_advanced(self):
  274. class Foo(object):
  275. def __init__(self, data=None):
  276. self.data = data
  277. def __repr__(self):
  278. return "Foo id %d, data %s" % (self.id, self.data)
  279. self.mapper_registry.map_imperatively(Foo, foo)
  280. class Bar(Foo):
  281. def __repr__(self):
  282. return "Bar id %d, data %s" % (self.id, self.data)
  283. self.mapper_registry.map_imperatively(Bar, bar, inherits=Foo)
  284. class Blub(Bar):
  285. def __repr__(self):
  286. return "Blub id %d, data %s, bars %s, foos %s" % (
  287. self.id,
  288. self.data,
  289. repr([b for b in self.bars]),
  290. repr([f for f in self.foos]),
  291. )
  292. self.mapper_registry.map_imperatively(
  293. Blub,
  294. blub,
  295. inherits=Bar,
  296. properties={
  297. "bars": relationship(Bar, secondary=blub_bar, lazy="joined"),
  298. "foos": relationship(Foo, secondary=blub_foo, lazy="joined"),
  299. },
  300. )
  301. sess = fixture_session()
  302. f1 = Foo("foo #1")
  303. b1 = Bar("bar #1")
  304. b2 = Bar("bar #2")
  305. bl1 = Blub("blub #1")
  306. for o in (f1, b1, b2, bl1):
  307. sess.add(o)
  308. bl1.foos.append(f1)
  309. bl1.bars.append(b2)
  310. sess.flush()
  311. compare = repr(bl1)
  312. blubid = bl1.id
  313. sess.expunge_all()
  314. result = sess.query(Blub).all()
  315. print(result)
  316. self.assert_(repr(result[0]) == compare)
  317. sess.expunge_all()
  318. x = sess.query(Blub).filter_by(id=blubid).one()
  319. print(x)
  320. self.assert_(repr(x) == compare)