2010-06-30 103 views
0

我遇到过使用一个表来存储用户和组相关数据的情况。该栏称为简档。所以,基本上这个表格是多对多表格,用于一个用户属于多个组或者一个组中有许多用户的情况。SQLAlchemy递归多对多关系

我有点困惑应该如何描述?

下面是类的简单介绍。

Entity relationship model

model

user_group_table = Table('user_group', metadata, 
Column('user_id', Integer,ForeignKey('profiles.id', 
    onupdate="CASCADE", ondelete="CASCADE")), 
Column('group_id', Integer, ForeignKey('profiles.id', 
    onupdate="CASCADE", ondelete="CASCADE")) 
) 

class Profile(Base) 
    __tablename__ = 'profiles' 

    id = Column(Integer, autoincrement=True, primary_key=True) 
    name = Column(Unicode(16), unique=True) # This can be either user-/groupname 
    groups = relationship('Profile', secondary=user_group_table, backref = 'users') 
    users = relationship('Profile', secondary=user_group_table, backref = 'groups') 

#Example of the usage: 
user = Profile() 
user.name = 'Peter' 

salesGroup = Profile() 
salesGroup.name = 'Sales' 

user.groups.append(salesGroup) 

salesGroup.users 
>[peter] 
+0

一般来说,对于多对多,您需要3个表格 - 比较中的两个对象各一个,第三个表格包含两个满足关系的对象的主键的记录。 这就是说,我不知道我明白这个问题... – 2010-06-30 13:11:42

回答

4

首先,我同意Raven的评论,你应该使用单独的表为UsersGroups。原因是,如果User可能有其他Users作为users关系,并且关系树中可能有循环,则可能会得到一些不一致的数据。

说了这么多,使关系工作其声明如下:

... 
class Profile(Base): 
    __tablename__ = 'profiles' 
    id = Column(Integer, primary_key=True, autoincrement=True) 
    name = Column(Unicode(16), unique=True) # This can be either user-/groupname 
    groups = relationship('Profile', 
       secondary=user_group_table, 
       primaryjoin=user_group_table.c.user_id==id, 
       secondaryjoin=user_group_table.c.group_id==id, 
       backref='users') 
... 

另见Specifying Alternate Join Conditions to relationship()文档部分。

+0

谢谢范 由于软件的类型,我们更容易将所有数据存储到同一张表。这是一些用户将作为一个组进行操作的功能的一部分。 起初我也很怀疑这个模型,但是由于它似乎简化了其他软件,所以我决定给它一个很好的解决方案。 – Heikki 2010-07-01 08:33:27

+0

祝你好运。该模型可能很简单,但您需要确保数据质量。 – van 2010-07-01 10:57:59