2016-03-17 44 views
2

我有以下實體,每個在我的數據庫中的表: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也有作用2在應用程序1中。

我有爲用戶,應用程序和角色定義的sqlalchemy映射。我希望User對象具有Application對象列表,並且對於每個Application對象,該對象都將包含一個Role對象列表。

從閱讀sqlalchemy的文檔看來,這種類型的關係是不可能映射的,我發現在stackoverflow上只有幾個其他問題,而這些問題都沒有被回答。這似乎是一個相對正常的3NF數據庫關係(我的整個數據模型中有4個關係),是否可以用sqlalchemy以某種方式設置它?我可以在大約10分鐘內用純SQL完成這件事,但我不想扔掉SqlAlchemy的所有其他有用功能,但如果我無法以某種方式工作,那麼我的應用程序將無法發貨。

此外,請不要暗示,只是我改變我的數據模型或denormalize數據庫或以任何方式混亂。這種性質的答案不會幫助我。我很高興能夠改變我的對象模型或添加額外的對象,如果我需要以某種方式神奇地將這個表映射到2個對象或類似奇怪的東西,但我無法更改數據模型。

+0

我仍然沒有找到這方面的好解決方案,但我最終創建了一個單獨的UserAppRole對象,並在我的User對象中使用了一個關係將它加入UserAppRole。由於我可以加載應用程序和角色對象(並且每個對象中只有很少的對象),因此持久層僅在id不夠的情況下(主要用於顯示在用戶界面中)手動掛接這些值。如果我在接下來的幾天裏沒有得到更好的答案,我會發佈一個更詳細的答案。 –

回答

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文檔似乎表明這些必須用於自引用表,並且我還沒有找到一種方法來使這種情況適用於此特定情況。