我正在尝试建立一个非常典型的权限结构模型,其中可以将User
模型(我网站的人类用户)分配给某些Roles
,而每个Roles
都有一些Permissions
。
如果我能直接从relationship
到User
得到一个Permission
,那将真的很有帮助。这样,我可以从数据库中获取一个 user (实例),然后执行user.permissions
来获得他的权限,进行一些过滤以检查用户是否具有特定的Permission
,将它们预先加载...总而言之:relationship
附带的所有好东西。
viewonly
关系将是完美的。正如Mike Bayer在a very similar question中提到的那样,我无法写到User.permissions
,因为我们不知道要使用哪个'Role'或在 中插入它。
我创建了两个中间表:
User -- M2M --> Role(s) -- M2M --> Permission(s)
| ^
+-------- user.permissions -----------+
users_roles
通过其主键(ID)将user
连接到其roles
roles_permissions
将每个role
连接到其permissions
,这是我的表结构(简化了问题,但即使是完整版也很典型,而且...简单)
class User(DeclarativeBase, Mixin):
__tablename__ = 'users'
email = Column(String(25), nullable=False)
_users_roles = Table('users_roles', DeclarativeBase.metadata,
Column('user_id', ForeignKey('users.id', ...
Column('role_id', ForeignKey('roles.id', ...
PrimaryKeyConstraint('user_id', 'role_id',),
)
class Role(DeclarativeBase, Mixin):
__tablename__ = 'roles'
name = Column(Text(), nullable=False, unique=True)
users = relationship("User", secondary=_users_roles, backref="roles")
_roles_permissions = Table('roles_permissions', DeclarativeBase.metadata,
Column('role_id', ForeignKey('roles.id', ...
Column('permission_id', ForeignKey('permissions.id', ...
PrimaryKeyConstraint('role_id', 'permission_id',),
)
class Permission(DeclarativeBase, Mixin):
__tablename__ = 'permissions'
key = Column(Text, nullable=False, unique=True,)
我看到this other answer看起来非常有前途,但是我似乎无法使其工作。老实说,我一直在尝试很多组合,我想说我最想知道的就是这个:
permissions = relationship('Permission',
secondary="""join(User, users_roles,
User.id == users_roles.c.user_id
).join(roles_permissions,
users_roles.c.role_id == roles_permissions.c.role_id
).join(
Permission, roles_permissions.c.permission_id == Permission.id
)""",
viewonly=True,
)
哪个给我这个错误:
sqlalchemy.exc.ArgumentError: Relationship User.permissions
could not determine any unambiguous local/remote column pairs
based on join condition and remote_side arguments. Consider
using the remote() annotation to accurately mark those elements
of the join condition that are on the remote side of the relationship.
任何提示将不胜感激。预先谢谢你。
答案 0 :(得分:2)
辅助表不应包括相关表本身,而应包括它们之间的关联:
permissions = relationship(
'Permission',
secondary="""join(users_roles, roles_permissions,
users_roles.c.role_id == roles_permissions.c.role_id)""",
viewonly=True,
)
在辅助数据库中具有要联接的表会使试图通过辅助数据库查找User
和Permission
之间的外键关系的自动化感到困惑。