sqlalchemy-通过一个表加入三个实体

时间:2016-03-17 21:22:00

标签: python mysql sqlalchemy

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

User
Application 
Role

我有另一个名为“user_app_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_id,application_id和role_id都是用户,应用程序和角色表中的外键。

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

我为用户,应用程序和角色定义了sqlalchemy映射。我想要的是User对象以某种方式具有Application对象的列表,并且对于每个Application对象,该对象将包含Role对象的列表。

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

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

1 个答案:

答案 0 :(得分:0)

好的,我可以确定,在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加载应用程序和角色对象,这在我的用户对象的审批列表中已经足够方便了。

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

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

相关问题