2010-06-30 4 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 таблицы - по одному для каждого из двух объектов в сравнении, а третье - записи, содержащие первичные ключи двух объектов, которые удовлетворяют соотношению. Это, я не уверен, что я понимаю вопрос ... –

ответ

4

Прежде всего, я согласен с комментарием Ворона, что вы должны использовать отдельные таблицы для Users и Groups. Причина в том, что вы можете получить некоторые несогласованные данные, где 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

Спасибо Van Из-за типа программного обеспечения нам легче хранить все данные в одной таблице. Это часть функциональности, которую некоторые пользователи будут действовать как группа. Поначалу я тоже очень подозрительно относился к этой модели, но, поскольку это, похоже, упростило остальную часть программного обеспечения, я решил дать ему шанс. – Heikki

+0

Удачи вам в этом. Модель может быть простой, но вам необходимо обеспечить качество данных. – van

Смежные вопросы