Source code for examples.large_collection.large_collection

  1. from sqlalchemy import Column
  2. from sqlalchemy import create_engine
  3. from sqlalchemy import ForeignKey
  4. from sqlalchemy import Integer
  5. from sqlalchemy import MetaData
  6. from sqlalchemy import String
  7. from sqlalchemy import Table
  8. from sqlalchemy.orm import mapper
  9. from sqlalchemy.orm import relationship
  10. from sqlalchemy.orm import sessionmaker
  11. meta = MetaData()
  12. org_table = Table(
  13. "organizations",
  14. meta,
  15. Column("org_id", Integer, primary_key=True),
  16. Column("org_name", String(50), nullable=False, key="name"),
  17. mysql_engine="InnoDB",
  18. )
  19. member_table = Table(
  20. "members",
  21. meta,
  22. Column("member_id", Integer, primary_key=True),
  23. Column("member_name", String(50), nullable=False, key="name"),
  24. Column(
  25. "org_id",
  26. Integer,
  27. ForeignKey("organizations.org_id", ondelete="CASCADE"),
  28. ),
  29. mysql_engine="InnoDB",
  30. )
  31. class Organization(object):
  32. def __init__(self, name):
  33. self.name = name
  34. class Member(object):
  35. def __init__(self, name):
  36. self.name = name
  37. mapper(
  38. Organization,
  39. org_table,
  40. properties={
  41. "members": relationship(
  42. Member,
  43. # Organization.members will be a Query object - no loading
  44. # of the entire collection occurs unless requested
  45. lazy="dynamic",
  46. # Member objects "belong" to their parent, are deleted when
  47. # removed from the collection
  48. cascade="all, delete-orphan",
  49. # "delete, delete-orphan" cascade does not load in objects on
  50. # delete, allows ON DELETE CASCADE to handle it.
  51. # this only works with a database that supports ON DELETE CASCADE -
  52. # *not* sqlite or MySQL with MyISAM
  53. passive_deletes=True,
  54. )
  55. },
  56. )
  57. mapper(Member, member_table)
  58. if __name__ == "__main__":
  59. engine = create_engine(
  60. "postgresql://scott:tiger@localhost/test", echo=True
  61. )
  62. meta.create_all(engine)
  63. # expire_on_commit=False means the session contents
  64. # will not get invalidated after commit.
  65. sess = sessionmaker(engine, expire_on_commit=False)()
  66. # create org with some members
  67. org = Organization("org one")
  68. org.members.append(Member("member one"))
  69. org.members.append(Member("member two"))
  70. org.members.append(Member("member three"))
  71. sess.add(org)
  72. print("-------------------------\nflush one - save org + 3 members\n")
  73. sess.commit()
  74. # the 'members' collection is a Query. it issues
  75. # SQL as needed to load subsets of the collection.
  76. print("-------------------------\nload subset of members\n")
  77. members = org.members.filter(member_table.c.name.like("%member t%")).all()
  78. print(members)
  79. # new Members can be appended without any
  80. # SQL being emitted to load the full collection
  81. org.members.append(Member("member four"))
  82. org.members.append(Member("member five"))
  83. org.members.append(Member("member six"))
  84. print("-------------------------\nflush two - save 3 more members\n")
  85. sess.commit()
  86. # delete the object. Using ON DELETE CASCADE
  87. # SQL is only emitted for the head row - the Member rows
  88. # disappear automatically without the need for additional SQL.
  89. sess.delete(org)
  90. print(
  91. "-------------------------\nflush three - delete org, "
  92. "delete members in one statement\n"
  93. )
  94. sess.commit()
  95. print("-------------------------\nno Member rows should remain:\n")
  96. print(sess.query(Member).count())
  97. sess.close()
  98. print("------------------------\ndone. dropping tables.")
  99. meta.drop_all(engine)