[英]Multiple joins with two association tables in SQLAlchemy?
我有这个(简化但有效的)代码来处理工作区的概念,其中每个工作区都可以有成员(分配给工作区的用户)和团队(也属于工作区)。
import json
from datetime import datetime
from sqlalchemy import create_engine
from sqlalchemy import Column, String, DateTime, Boolean, Integer, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship, backref
db_uri = "postgresql://postgres:postgres@127.0.0.1/test_db"
db = create_engine(db_uri)
Base = declarative_base()
class UserWorkspaceRole(Base):
__tablename__ = "user_workspace_role"
user_id = Column(Integer, ForeignKey('user.id'), primary_key=True)
workspace_id = Column(Integer, ForeignKey('workspace.id'), primary_key=True)
role_id = Column(Integer, ForeignKey('role.id'), primary_key=True)
class UserWorkspaceTeam(Base):
__tablename__ = "user_workspace_team"
user_id = Column(Integer, ForeignKey('user.id'), primary_key=True)
workspace_id = Column(Integer, ForeignKey('workspace.id'), primary_key=True)
team_id = Column(Integer, ForeignKey('team.id'), primary_key=True)
class User(Base):
__tablename__ = "user"
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String)
team_workspaces = relationship(UserWorkspaceTeam, cascade="all, delete-orphan", backref="user")
role_workspaces = relationship(UserWorkspaceRole, cascade="all, delete-orphan", backref="user")
class Workspace(Base):
__tablename__ = "workspace"
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String)
team_users = relationship(UserWorkspaceRole, cascade="all, delete-orphan", backref="workspace")
role_users = relationship(UserWorkspaceTeam, cascade="all, delete-orphan", backref="workspace")
class Role(Base):
__tablename__ = "role"
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String)
role = relationship(UserWorkspaceRole, cascade="all, delete-orphan", backref="role")
class Team(Base):
__tablename__ = "team"
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String)
team = relationship(UserWorkspaceTeam, cascade="all, delete-orphan", backref="team")
Session = sessionmaker(db)
session = Session()
Base.metadata.create_all(db)
#Base.metadata.drop_all(db)
# Add roles
role_owner = Role(name="owner")
role_member = Role(name="member")
roles = [role_owner, role_member]
session.add_all(roles)
session.commit()
# Add teams
team_1 = Team(name="Team_1")
team_2 = Team(name="Team_2")
teams = [team_1, team_2]
session.add_all(teams)
session.commit()
# Add users
user1 = User(name="User_1")
user2 = User(name="User_2")
user3 = User(name="User_3")
users = [user1, user2, user3]
session.add_all(users)
session.commit()
workspace1 = Workspace(name="Apple")
test1 = UserWorkspaceRole(user=user1,workspace=workspace1, role_id="1")
test2 = UserWorkspaceRole(user=user2,workspace=workspace1, role_id="2")
test3 = UserWorkspaceRole(user=user3,workspace=workspace1, role_id="2")
test4 = UserWorkspaceTeam(user=user1,workspace=workspace1, team_id="1")
test5 = UserWorkspaceTeam(user=user1,workspace=workspace1, team_id="2")
records = [test1, test2, test3, test4, test5]
session.add_all(records)
session.commit()
x = session.query(UserWorkspaceRole).join(User).join(Workspace).join(Role).filter(Workspace.id == '1').all()
members = []
for n in range(len(x)):
members.append(
{
"workspace": x[n].workspace.id,
"name": x[n].user.name,
"role": x[n].role.name
}
)
print(json.dumps(members, indent=4))
这给出了以下输出:
[
{
"workspace": 1,
"name": "User_1",
"role": "owner"
},
{
"workspace": 1,
"name": "User_3",
"role": "member"
},
{
"workspace": 1,
"name": "User_2",
"role": "member"
}
]
我想要实现的是将用户所属的团队添加到列表中的每个字典中。 我可以通过一个查询来实现这一目标吗? 我也尝试加入 UserWorkspaceTeam,但可能我遗漏了一些东西(我是 db 的新手)。
我想要的输出应该是这样的:
[
{
"workspace": 1,
"name": "User_1",
"role": "owner",
"teams": [
{"id": "1", "name": "Team_1"},
{"id": "2", "name": "Team_2"}
]
},
{
"workspace": 1,
"name": "User_3",
"role": "member"
},
{
"workspace": 1,
"name": "User_2",
"role": "member"
}
]
我怎样才能做到这一点?
在for
循环中使用range()
函数时,您指定的上限不足 1。 尝试像以前一样加入UserWorkspaceTeam
,但这次添加到范围函数的上限,允许您到达最后一个索引。 希望这会有所帮助。
x = session.query(UserWorkspaceRole).join(User).join(Workspace).join(Role).join(UserWorkspaceTeam).filter(Workspace.id == '1').all()
members = []
# The range() function includes values from 0 until a bound you specify but not including it.
for n in range(len(x)+1):
members.append(
{
"workspace": x[n].workspace.id,
"name": x[n].user.name,
"role": x[n].role.name,
}
)
print(json.dumps(members, indent=4))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.