Python 与「;“跳跃”;通过SqlAlchemy中的M2M关系(用户->;角色->;权限)

Python 与「;“跳跃”;通过SqlAlchemy中的M2M关系(用户->;角色->;权限),python,sqlalchemy,relationship,m2m,Python,Sqlalchemy,Relationship,M2m,我试图建立一个非常典型的权限结构模型,其中用户模型(我网站的人类用户)可以分配给一些角色,而这些角色中的每一个都有一些权限 如果我能从用户直接获得权限的关系,那将非常有帮助。这样,我可以从数据库中获取一个用户(实例),只需执行user.permissions即可获取他的权限,进行一些筛选以检查用户是否具有特定的权限,并将其预加载。。。总之:所有与关系相关的好东西 viewonly关系将非常好。正如Mike Bayer在中提到的那样,我不能向User.permissions写信,因为我们不知道要使

我试图建立一个非常典型的权限结构模型,其中
用户
模型(我网站的人类用户)可以分配给一些
角色
,而这些
角色中的每一个都有一些
权限

如果我能从
用户
直接获得
权限
关系
,那将非常有帮助。这样,我可以从数据库中获取一个用户(实例),只需执行
user.permissions
即可获取他的权限,进行一些筛选以检查用户是否具有特定的
权限
,并将其预加载。。。总之:所有与
关系相关的好东西

viewonly
关系将非常好。正如Mike Bayer在中提到的那样,我不能向
User.permissions
写信,因为我们不知道要使用哪个“角色”或在哪里插入它

我创建了两个中间表:

User -- M2M --> Role(s) -- M2M --> Permission(s)
 |                                     ^
 +-------- user.permissions -----------+
  • 用户\u角色
    通过其主键(ID)将
    用户
    连接到其
    角色
  • 角色\u权限
    将每个
    角色
    连接到其
    权限
这是我的表格结构(问题简化了,但即使是完整的版本也非常典型和简单)

我看到这看起来很有希望,但我似乎无法让它发挥作用。老实说,我已经尝试了很多组合,我想说我得到的最远的结果是:

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,
)

将要联接的表放在次表中会使试图通过次表查找
用户
权限
之间的外键关系的自动化操作变得混乱。

OMG。。。小时!!。。。我花了几个小时尝试不同的东西组合!!非常感谢。这里的概念是连接有效地创建了一个关联表吗?@supershot。您可以使用about任意表(存在外键)作为辅助表,无论它是联接、选择或类似操作的结果:。由于SQLA处理重复数据消除实体的方式,即使联接多次生成相同的权限id也不是问题。即使联接多次生成相同的权限id也不是问题。我可以对此进行评估。我创建了一个测试,其中一个
用户
属于两个不同的角色,每个角色具有相同的权限,并且在我的
用户中。权限
关系中,我只获得一个
权限
实例,即使我没有在
关系
中指定
collection\u class=set
。这让我有点担心(获得重复权限),但不是:这不会发生。。。它工作得很好:+1:
permissions = relationship(
    'Permission',
    secondary="""join(users_roles, roles_permissions, 
                      users_roles.c.role_id == roles_permissions.c.role_id)""",
    viewonly=True,
)