Python sqlalchemy-通过一个表连接的三个实体

Python sqlalchemy-通过一个表连接的三个实体,python,mysql,sqlalchemy,Python,Mysql,Sqlalchemy,我有以下实体,每个实体都是我数据库中的一个表: User Application Role 我有另一个名为“user\u app\u role”的表,如下所示: table user_app_role( user_id int not null , application_id int not null, role_id int not null, primary key(user_id, application_id, role_id) ) 其中,user\u id、applicatio

我有以下实体,每个实体都是我数据库中的一个表:

User
Application 
Role
我有另一个名为“user\u app\u role”的表,如下所示:

table user_app_role(
user_id int not null ,
application_id int not null,
role_id int not null,
primary key(user_id, application_id, role_id)
)
其中,user\u id、application\u id和role\u id都是user、application和role表上的外键

该表中的条目表示用户在特定应用程序中具有特定角色,因此一行可能返回
1,1,1
,表示用户1在应用程序1中具有角色1。类似地,
1,2,1
意味着用户1在应用程序1中也有角色2

我已经为用户、应用程序和角色定义了sqlalchemy映射。我希望用户对象以某种方式拥有一个应用程序对象列表,对于每个应用程序对象,该对象将包含一个角色对象列表

通过阅读sqlalchemy的文档,似乎无法映射这种类型的关系,我在stackoverflow上只发现了几个其他问题,这些问题都没有答案。这似乎是一个相对正常的3NF数据库关系(在我的整个数据模型中有4个),是否可以在sqlalchemy中进行设置?我可以用纯SQL在大约10分钟内完成这一切,但我不想放弃SqlAlchemy的所有其他有用功能,但如果我无法以某种方式使其工作,那么我的应用程序将无法发布


另外,请不要建议我仅仅改变我的数据模型或对数据库进行非规范化,或者以任何方式弄乱它。那种性质的回答对我没有帮助。如果我需要神奇地将这个表映射到2个对象或类似的奇怪对象,我很乐意更改我的对象模型或添加其他对象,但我无法更改数据模型。

好的,据我所知,在SqlAlchemy中创建此场景的实际映射是不可能的,因此我的解决方法如下:

class UserAppRole(Base):
    __tablename__ = 'userapprole'
    user_id = Column(stuff, ForeignKey(users.id))
    role_id = Column(otherstuff, ForeignKey(roles.id))
    app_id = Column(morestuff, ForeignKey(apps.id))
我已经决定,在我的应用程序的域中,用户与应用程序具有角色,因此此新对象的关系将取决于用户:

class User(Base):
    __tablename__ = 'users'
    approles = relationship(UserAppRole, backref=backref('app_user_role', uselist=True))
    # other columns, relationships, etc.
这很有效,因为当我加载一个用户时,我想知道他们以任何方式访问什么应用程序,我想知道他们对这些应用程序有什么角色。在我的领域中,角色是一种东西,应用程序也是一种东西,这些东西相对较少,而且它们往往不会改变(尽管这不是此解决方案的要求)。重要的是,我可以根据应用程序和角色对象的ID加载它们,这非常方便,我现在已经在我的用户对象的Approvles列表中了

要将这一切绑定在一起,我要做的最后一件事是使用存储库来处理我的用户对象的持久性。当我加载一个用户时,SqlAlchemy将用ID填充Approvles列表。然后,我可以手动加载应用程序和角色,并为具有角色列表的应用程序构建字典。现在,当我向应用程序添加用户角色时,我需要传入应用程序对象(知道哪些角色有效)和角色对象(可能对该应用程序有效,也可能无效)。这两个都有ID,所以对我来说,更新字典和/或Approvles列表以包含我想要的内容是非常简单的。如果我尝试使用不存在的角色id或应用程序id写入DB,那么数据库中的约束将拒绝插入/更新,我将得到一个异常


这不是我的理想解决方案,但它在我遇到的两种情况下都非常有效。如果有人有更好的解决方案,请发布。我觉得复合邻接列表对于这个场景应该很有用,但当前的SqlAlchemy文档似乎表明,这些列表必须用于自引用表,我还没有找到一种方法使其适用于这个特定场景。

我仍然没有找到很好的解决方案,但我最终创建了一个单独的UserAppRole对象,并使用我的用户对象中的关系将其连接到UserAppRole。由于我可以加载应用程序和角色对象(每个对象都很少),所以我的持久性层只是在id不足的情况下(主要是在UI中的某个地方显示)手动连接这些值。如果在接下来的几天里我没有得到更好的答案,我会发布一个更详细的答案。