diff --git a/relationship/association_object_ternary.py b/relationship/association_object_ternary.py index 30a1389b1389f972de61dc7aee9a468913e67472..484d459e3b44cf9818e7edc76153f7a3719d9780 100644 --- a/relationship/association_object_ternary.py +++ b/relationship/association_object_ternary.py @@ -8,6 +8,9 @@ from sqlalchemy import Column, ForeignKey, Integer, Text, DateTime from sqlalchemy.orm import declarative_base, relationship from sqlalchemy.orm.session import Session +# Mix ORM with Core SQL Expression language ??? +# https://docs.sqlalchemy.org/en/14/core/tutorial.html +from sqlalchemy import select Base = declarative_base() @@ -25,9 +28,15 @@ class UserOrgRole(Base): ) # I do not know what the relationship could back populate, org or role ??? - user = relationship("User") - org = relationship("Org") - role = relationship("Role") + user = relationship("User", back_populates="orgsroles") + org = relationship("Org", back_populates="usersroles") + role = relationship("Role", back_populates="usersorgs") + + def __repr__(self): + return ( + f"<UserOrgRole (user_id={self.user_id}, org_id={self.org_id}, " + f"role_id={self.role_id})>" + ) class User(Base): @@ -38,12 +47,43 @@ class User(Base): fullname = Column(Text, nullable=False) account_type = Column(Text, nullable=False) + orgsroles = relationship("UserOrgRole", back_populates="user") + def __repr__(self): return ( f"<User (username={self.username}, fullname={self.fullname}, " f"account_type={self.account_type})>" ) + def get_roles(self, session): + stmt = ( + select(Role) + .select_from(UserOrgRole) + .join(Role, UserOrgRole.role_id == Role.id) + .where(UserOrgRole.user_id == self.id) + ) + print(stmt) + results = session.execute(stmt) + print(results) + # <sqlalchemy.engine.result.ChunkedIteratorResult object at 0x7f35d3bdd040> + # https://docs.sqlalchemy.org/en/14/core/connections.html#sqlalchemy.engine.ChunkedIteratorResult + for row in results: + # Pourquoi row semble être un tuple qui contient l'objet ? + # type(row) + # <class 'sqlalchemy.engine.row.Row'> + # type(row[0]) + # <class '__main__.Role'> + print(row[0].name) + + def get_uor(self, session): + # https://docs.sqlalchemy.org/en/14/orm/session_api.html?highlight=session%20execute#sqlalchemy.orm.Session.execute + stmt = select(UserOrgRole).where(UserOrgRole.user_id == self.id) + print(stmt) + results = session.execute(stmt) + for row in results: + uor = row[0] + print(uor) + class Org(Base): __tablename__ = "org" @@ -53,6 +93,8 @@ class Org(Base): slug = Column(Text, index=True, nullable=False) created_at = Column(DateTime) + usersroles = relationship("UserOrgRole", back_populates="org") + def __repr__(self): return ( f"<Org (name={self.name}, slug={self.slug}, " @@ -66,6 +108,8 @@ class Role(Base): id = Column(Integer, primary_key=True) name = Column(Text, index=True, nullable=False) + usersorgs = relationship("UserOrgRole", back_populates="role") + def __repr__(self): return f"<Role (name={self.name})>" @@ -85,17 +129,71 @@ if __name__ == "__main__": fullname="Jack London", account_type="member", ) + + u2 = User( + username="jdoe", + fullname="John Doe", + account_type="member", + ) + o1 = Org(name="o1", slug="o1", created_at=datetime.utcnow()) + o2 = Org(name="o2", slug="o2", created_at=datetime.utcnow()) + owner = Role(name="owner") + reader = Role(name="reader") uor1 = UserOrgRole() uor1.user = u1 uor1.org = o1 uor1.role = owner + uor2 = UserOrgRole() + uor2.user = u2 + uor2.org = o1 + uor2.role = reader + + uor3 = UserOrgRole() + uor3.user = u2 + uor3.org = o2 + uor3.role = owner + with session.begin(): session.add(u1) + session.add(u2) session.add(o1) + session.add(o2) session.add(owner) + session.add(reader) session.add(uor1) + session.add(uor2) + session.add(uor3) + + # u1.get_uor(session) + u1.get_roles(session) + + print(u1) + print(u1.orgsroles[0].org) + print(u1.orgsroles[0].role) + + print(u2) + print(u2.orgsroles[0].org) + print(u2.orgsroles[0].role) + + print(o1) + print(owner) + + """ + # Mix ORM with Core SQL Expression language ??? + user = Base.metadata.tables["user"] + + with engine.connect() as conn: + stmt = select(user) + for row in conn.execute(stmt): + print(row) + """ + + # Y a-t-il des pistes dans les ORM examples ? + # https://docs.sqlalchemy.org/en/14/_modules/examples/join_conditions/threeway.html + + # https://dba.stackexchange.com/questions/150865/how-to-model-a-three-way-association-that-involves-product-category-and-label