使用所有权所有权或组成员身份的声明式关系表示,使用SQLAlchemy

时间:2018-08-17 21:13:19

标签: python postgresql sqlalchemy

A Postgres数据库中有一些表:

  • users(系统中的用户)
  • groups(组用户可以是其中的一部分)
  • group_memberships(许多映射到组和用户)
  • resources(用户要访问的对象)

如果用户拥有资源或资源由其组拥有,则用户可以访问资源。当前,这是通过uid表中的gid(用户ID)和resources(组ID)外键列实现的。使用group_memberships表作为辅助数据库,我已经在用户和组之间建立了映射:

GroupMembership = Table('group_memberships', Base.metadata,
    Column('gid', Integer, ForeignKey('users.uid'), primary_key=True),
    Column('uid', Integer, ForeignKey('groups.gid'), primary_key=True))
Group.users = relationship(User, secondary=GroupMembership, lazy=True)
User.groups = relationship(Group, secondary=GroupMembership, lazy=True)

资源由用户或组拥有:

class Resource(Base):
    # ...
    uid = Column(Integer, ForeignKey('users.uid'), nullable=True)
    gid = Column(Integer, ForeignKey('groups.gid'), nullable=True)
    # ...

usersgroups的模型会映射回其拥有的资源,例如:

class User(Base):
    # ...
    resources = relationship('Resource', backref='user', lazy=True, viewonly=True)
    # ...

当前,如果我想查询用户可用的所有资源,我将合并user.resources中可用的所有资源,然后遍历所有用户组并添加这些资源:

resources = user.resources + [r for group in user.groups for r in group.resources]

但是,我想要在数据库中执行此映射,而不是遍历所有组。看起来这应该很简单,但是我不确定我对SQLAlchemy文档的理解是否足够充分,可以完全将其映射出来。本质上我正在寻找的东西等同于例如SQL查询uid=1用户:

SELECT * FROM resources
WHERE
    uid=1 OR
    gid in (SELECT gid FROM group_memberships WHERE uid=1)

有什么想法可以将其应用于sqlalchemy.orm.relationship吗?也许我的resources所有权模型需要调整为除具有uidgid列以外的其他内容?

1 个答案:

答案 0 :(得分:0)

session.query(Resource).filter(
     Resource.gid.in_(some_user.groups.gid) | (Resource.uid == some_user.uid))