繁体   English   中英

SQLAlchemy 中具有两个关联表的多个连接?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM