【发布时间】:2011-11-10 16:43:24
【问题描述】:
我有一个表 Users 和一个表 Friends 将用户映射到其他用户,因为每个用户可以有很多朋友。这个关系显然是对称的:如果用户 A 是用户 B 的朋友,那么用户 B 也是用户 A 的朋友,我只存储这个关系一次。 Friends 表除了两个用户 ID 之外还有其他字段,因此我必须使用关联对象。
我试图在 Users 类中以声明式的方式定义这种关系(它扩展了声明式基础),但我似乎无法弄清楚如何做到这一点。我希望能够通过属性friends访问给定用户的所有朋友,所以说friends = bob.friends。
解决这个问题的最佳方法是什么?我尝试了许多不同的设置来在这里发布,但由于各种原因,它们都没有工作。
编辑:我最近的尝试是这样的:
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
# Relationships
friends1 = relationship('Friends', primaryjoin=lambda: id==Friends.friend1ID)
friends2 = relationship('Friends', primaryjoin=lambda: id==Friends.friend2ID)
class Friends(Base):
__tablename__ = 'friends'
id = Column(Integer, primary_key=True)
friend1ID = Column(Integer, ForeignKey('users.id') )
friend2ID = Column(Integer, ForeignKey('users.id') )
status = Column(Integer)
# Relationships
vriend1 = relationship('Student', primaryjoin=student2ID==Student.id)
vriend2 = relationship('Student', primaryjoin=student1ID==Student.id)
然而,这会导致以下错误:
InvalidRequestError: Table 'users' is already defined for this MetaData instance. Specify 'extend_existing=True' to redefine options and columns on an existing Table object.
我必须承认,在这一点上,由于许多失败的尝试,我完全糊涂了,并且可能在上面犯了不止一个愚蠢的错误。
【问题讨论】:
-
附加字段是什么?我想知道他们是否对两个朋友都很常见,或者是
directional。 -
看另一个关于 SO [stackoverflow.com/questions/7120774/…: 它具有相似的结构,Gary 试图通过使用视图来解决对称性。我个人不是这个想法的忠实拥护者,但您可能想尝试一下。
-
附加字段是一个状态字段,它指示 1) 好友请求是否已发送或 b) 已发送并接受。将来我可能需要更多领域。加里的方法确实有点难看,我非常想要一个更好的解决方案。有人吗?
-
"请求已被接受?"被谁接受,或者朋友?对我来说,这听起来不像是一种对称的关系。您可能想要排除额外的字段,以便朋友关系确实是对称的,或者重新考虑对称要求并且只有两行,“a 是 b 的朋友,b 是 a 的朋友”,以便您可以捕获不对称更优雅。
-
这些是您定义的唯一模型,还是您在项目的其他地方定义了其他模型?
标签: python sqlalchemy many-to-many relationship declarative