如何使用SQLAlchemy实现用户可访问集合的查询(包含所有者与成员权限)
如何使用SQLAlchemy实现用户可访问集合的查询(包含所有者与成员权限)
嗨,你的模型结构已经搭得很清晰啦,要实现这个查询其实很简单,只需要把「用户是集合所有者」和「用户是集合成员」这两个条件用or_组合起来就行,我给你两种常用的实现方式:
方式一:利用SQLAlchemy Relationship的any()方法(推荐,代码更简洁)
这种方式直接借助你已经定义好的members关联关系,any()方法会自动帮你生成子查询,检查用户是否在集合的成员列表中:
from sqlalchemy import or_ from sqlalchemy.orm import Session from your_module import SetEntity # 替换成你的实际模块路径 def getAvailableSets(session: Session, userId: int) -> list[SetEntity]: return session.query(SetEntity).filter( or_( # 条件1:用户是集合的所有者 SetEntity.ownerId == userId, # 条件2:用户是集合的成员 SetEntity.members.any(id=userId) ) ).all()
方式二:手动关联中间表(贴近原生SQL逻辑)
如果你更习惯用原生SQL的join思路,也可以直接关联set_members中间表,完全对应你给出的SQL语句:
from sqlalchemy import or_ from sqlalchemy.orm import Session from your_module import SetEntity, SetMemberEntity # 替换成你的实际模块路径 def getAvailableSets(session: Session, userId: int) -> list[SetEntity]: return ( session.query(SetEntity) # 用outerjoin避免过滤掉没有成员的所有者集合 .outerjoin(SetMemberEntity, SetEntity.id == SetMemberEntity.c.set_id) .filter( or_( # 条件1:用户是集合的所有者 SetEntity.ownerId == userId, # 条件2:用户在集合的成员列表中 SetMemberEntity.c.member_id == userId ) ) # 去重:避免同一个集合因中间表的多条匹配记录而重复返回 .distinct() .all() )
验证测试用例
这两种方式都能完美匹配你的预期结果:
- 调用
getAvailableSets(session, 1)→ 返回[SetEntity(id=1, ...)] - 调用
getAvailableSets(session, 3)→ 返回[SetEntity(id=1, ...), SetEntity(id=2, ...)]
注意事项
- 确保你已经导入了
sqlalchemy的or_函数(你的原代码里写的_or是笔误); - 方式二中的
outerjoin是必须的:如果用普通join,会过滤掉没有成员的所有者集合;distinct用于避免同一个集合因中间表的多条匹配记录而重复返回; - 你的
SetEntity中members关联关系定义正确,所以any()方法可以正常工作。
备注:内容来源于stack exchange,提问作者Emma Grinberg
相关产品推荐
相关产品推荐

