通过 SQLAlchemy 选择多个多对多关系
Posted
技术标签:
【中文标题】通过 SQLAlchemy 选择多个多对多关系【英文标题】:Select through multiple many to many relationships via SQLAlchemy 【发布时间】:2013-07-17 06:47:05 【问题描述】:我希望能够通过 SQLAlchemy 中的多个多对多关系进行查询。
我有与组相关联的用户,这些组与角色相关联。所有关联都是多对多的。我想通过组获取与用户关联的角色列表。
这是我的精简模型:
class User(Model):
id = Column(Integer)
groups = relationship('Group', secondary=user_group)
class Group(Model):
id = Column(Integer)
roles = relationship('Role', secondary=role_group)
class Role(Model):
id = Column(Integer)
我对使用什么 SQL 有一个粗略的了解:
select distinct role.* from role, role_group
where role.id = role_group.role_id
and role_group.group_id in
(select "group".id from "group", user_group
WHERE user_group.user_id = 1
and "group".id = user_group."group.id")
但是我很难弄清楚如何将其转换为 SQLAlchemy...而且我不确定这里的 SQL 是否是执行此操作的最佳方法。
【问题讨论】:
【参考方案1】:试试这个
s = Session()
s.query(Role).join(User.groups).join(Group.roles).filter(User.id==1).all()
它将生成以下sql查询
SELECT role.id AS role_id
FROM user
JOIN user_group AS user_group_1 ON user.id = user_group_1.user_id
JOIN "group" ON "group".id = user_group_1.group_id
JOIN role_group AS role_group_1 ON "group".id = role_group_1.group_id
JOIN role ON role.id = role_group_1.role_id
WHERE user.id = 1;
但是 sqlalchemy 只会返回不同的角色(如果您将查询 Role.id 那么 sqlalchemy 将返回 sql 查询实际返回的内容)。
【讨论】:
完美。这正是我一直在寻找的。如果您在原始问题中注意到我实际上确实想要不同的角色(请参阅 SQL)。此外,这似乎比我上面写的更合适的 SQL。谢谢。【参考方案2】:我确实找到了我自己的问题的解决方案,该解决方案将生成接近我正在寻找的 SQL。但是,我相信 zaquest 的答案要好得多,并且会改用它。这只是为了后代。
这是我想出的查询:
s = Session()
s.query(Role).join(Role.groups).filter(
Group.id.in_(s.query(Group.id).join(User.groups)
.filter(User.id == self.id)))
这将生成以下 SQL
SELECT role.id AS role_id
FROM role JOIN role_group AS role_group_1 ON role.id = role_group_1.role_id
JOIN "group" ON "group".id = role_group_1.group_id
WHERE "group".id IN
(SELECT "group".id AS group_id
FROM "user" JOIN user_group AS user_group_1 ON "user".id = user_group_1.user_id
JOIN "group" ON "group".id = user_group_1."group.id"
WHERE "user".id = :id_1)
这类似于我正在寻找的 SQL。我忘记的关键是我可以使用另一个查询作为 SQLAlchemy 中 in
运算符的一部分。
【讨论】:
以上是关于通过 SQLAlchemy 选择多个多对多关系的主要内容,如果未能解决你的问题,请参考以下文章
深入浅出Flask(50):flask_sqlalchemy的创建多对多的关系表