我正在学习SQLAlchemy,我在做看似简单的操作时遇到了麻烦。如果我的问题是原始的和基本的,请原谅我,但我不能为我的生活弄清楚如何基本上加入我的两个表。
我的表是这样的:
class User(Base):
""" Basic User definition """
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(Unicode(255))
email = Column(Unicode(255), unique=True)
username = Column(Unicode(255), unique=True)
_password = Column('password', Unicode(60))
contacts = relationship('Contact', backref='users')
contact_groups = relationship('ContactGroups', backref='users')
contact_group_users = relationship('ContactGroupUsers', backref='users')
class Contact(Base):
__tablename__ = 'contacts'
id = Column(Integer, primary_key=True)
user_id = Column(Integer)
contact_id = Column(Integer)
__table_args__ = (ForeignKeyConstraint([contact_id], [User.id]), {})
class ContactGroups(Base):
__tablename__ = 'contact_groups'
id = Column(Integer, primary_key=True)
user_id = Column(Integer, ForeignKey('users.id'))
group_name = Column(Unicode(255))
contact_group_users = relationship('ContactGroupUsers', backref='contact_groups')
class ContactGroupUsers(Base):
__tablename__ = 'contact_group_users'
id = Column(Integer, primary_key=True)
group_id = Column(Integer, ForeignKey('contact_groups.id'))
user_id = Column(Integer, ForeignKey('users.id'))
我有我的主User
表。用户可以将其他用户添加为Contact
。为了帮助组织这些联系人,他们可以创建ContactGroups
。
Contact.user_id
和Contact.contact_id
应该是User.id
的外键。
ContactGroupUsers.group_id
是ContactGroup.id
的外键
每个ContactGroupUser.user_id
都是返回该用户User.id
的外键。
(也许这是一种可怕的方式......它可能是,但我正在学习。无论如何。)
当我查询特定组中的联系人时,我想检索filter(ContactGroupUsers.group_id == group_id).all()
中的所有行,然后从中将ContactGroupUsers.user_id
加入{{1}中的该用户的条目表。因此,我最终会得到一个结果:
Contact
那么,我的最后一个问题是,如何基于ContactGroupUsers.group_id | (and then the information present in the contacts table for that user)
加入我的两个表ContactGroupUsers
和Contacts
?或者,如果有一个固有的优越方法,请指出我正确的方向,所以我至少可以适当地学习。
感谢您的帮助。非常感谢。
答案 0 :(得分:1)
由于您在User
中将多个外键定义回Contact
,因此最好按如下方式定义它们:
from sqlalchemy.ext.associationproxy import association_proxy
class User( Base ):
__tablename__ = 'user'
id = Column( Integer, primary_key=True )
contacts = relationship( 'Contact',
primaryjoin = 'foreign( User.id )=remote( Contact.user_id )',
backref = 'user'
)
contact_groups = relationship( 'ContactGroup', backref='user' )
contact_group_users = relationship( 'ContactGroupUsers', backref='user' )
contact_users = association_proxy( 'contacts', 'contact' )
class Contact( Base ):
__tablename__ = 'contact'
id = Column( Integer, primary_key=True )
user_id = Column( Integer, ForeignKey( 'user.id' ) )
contact_id = Column( Integer, ForeignKey( 'user.id' ) )
contact = relationship( 'User',
primaryjoin = 'foreign( Contact.contact_id ) = remote( User.id )',
backref = 'user_contacts'
)
class ContactGroup( Base ):
__tablename__ = 'contact_group'
id = Column( Integer, primary_key=True )
user_id = Column( Integer, ForeignKey( 'user.id' ) )
class ContactGroupUser( Base ):
__tablename__ = 'contact_group_user'
id = Column( Integer, primary_key=True )
group_id = Column( Integer, ForeignKey( 'contact_group.id' ) )
user_id = Column( Integer, ForeignKey( 'user.id' ) )
contact_group = relationship( 'ContactGroup' )
以这种格式构建关系可能有些复杂,涉及aliased
个实例的用户。例如,您可以按如下方式进行查询,以指示某个group_id下的所有给定用户的联系人:
original_user = aliased( User )
contacts = db.session.query( User )\
.join( User.user_contacts )\
.join( original_user, original_user.id == Contact.user_id )\
.join( User.contact_group_users )\
.join( ContactGroupUser.contact_groups ).filter(
and_(
original_user.id == user_id,
contact_group.user_id == original_user.id,
contact_group.group_id == group_id
)
).all()