通过 SqlAlchemy 中的 M2M 关系与 "jump" 的关系(用户 -> 角色 -> 权限)
Relationship to "jump" through M2M relationships in SqlAlchemy (User -> Role -> Permission)
我正在尝试建立一个非常典型的权限结构模型,其中可以将 User
模型(我网站的人类用户)分配给某些 Roles
,并且每个 Roles
有一些 Permissions
.
如果我能从 User
直接得到 relationship
到 Permission
,那将非常有帮助。这样,我可以从数据库中获取一个 user(实例),然后执行 user.permissions
以获得他的权限,进行一些过滤以检查用户是否具有特定的 Permission
,让它们预加载...总而言之:relationship
.
附带的所有好东西
viewonly
关系就很好了。正如 Mike Bayer 在 a very similar question 中提到的,我不能写信给 User.permissions
因为我们不知道要使用哪个 'Role' 或 哪里 插入它。
我创建了两个中间 tables:
User -- M2M --> Role(s) -- M2M --> Permission(s)
| ^
+-------- user.permissions -----------+
users_roles
通过主键(ID) 将 user
连接到它的 roles
- 和
roles_permissions
将每个 role
连接到其 permissions
、
这是我的table结构(针对问题进行了简化,但即使是完整版也非常典型且...简单)
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.
如有任何提示,我们将不胜感激。提前谢谢你。
辅助不应包括相关表本身,而应包括它们之间的关联:
permissions = relationship(
'Permission',
secondary="""join(users_roles, roles_permissions,
users_roles.c.role_id == roles_permissions.c.role_id)""",
viewonly=True,
)
在辅助表中加入要连接的表会混淆试图通过辅助查找 User
和 Permission
之间的外键关系的自动化。
我正在尝试建立一个非常典型的权限结构模型,其中可以将 User
模型(我网站的人类用户)分配给某些 Roles
,并且每个 Roles
有一些 Permissions
.
如果我能从 User
直接得到 relationship
到 Permission
,那将非常有帮助。这样,我可以从数据库中获取一个 user(实例),然后执行 user.permissions
以获得他的权限,进行一些过滤以检查用户是否具有特定的 Permission
,让它们预加载...总而言之:relationship
.
viewonly
关系就很好了。正如 Mike Bayer 在 a very similar question 中提到的,我不能写信给 User.permissions
因为我们不知道要使用哪个 'Role' 或 哪里 插入它。
我创建了两个中间 tables:
User -- M2M --> Role(s) -- M2M --> Permission(s)
| ^
+-------- user.permissions -----------+
users_roles
通过主键(ID) 将 - 和
roles_permissions
将每个role
连接到其permissions
、
user
连接到它的 roles
这是我的table结构(针对问题进行了简化,但即使是完整版也非常典型且...简单)
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.
如有任何提示,我们将不胜感激。提前谢谢你。
辅助不应包括相关表本身,而应包括它们之间的关联:
permissions = relationship(
'Permission',
secondary="""join(users_roles, roles_permissions,
users_roles.c.role_id == roles_permissions.c.role_id)""",
viewonly=True,
)
在辅助表中加入要连接的表会混淆试图通过辅助查找 User
和 Permission
之间的外键关系的自动化。