SQLAlchemy 一对多关系澄清
Posted
技术标签:
【中文标题】SQLAlchemy 一对多关系澄清【英文标题】:SQLAlchemy one-to-many relationship clarification 【发布时间】:2016-03-16 02:15:07 【问题描述】:阅读 SQLAlchemy 文档后,我仍然不清楚实际上应该如何指定一对多关系。我将分解文档并解释为什么我感到困惑(http://docs.sqlalchemy.org/en/latest/orm/basic_relationships.html#one-to-many):
一对多关系在子表上放置一个外键 引用父级。
看起来我要在模型上放置一些 Column
属性,该属性将位于关系的“多”端。
relationship() 然后在父级上指定,作为引用由子级表示的项目集合:
这意味着父节点上有一些属性指定参与关系的“多”端的模型。
如果不是因为这样一种情况,我想定义两个一对多关系,关系双方的相同参与者,这对我来说完全有意义。
SQLAlchemy 如何知道关系“多”侧的ForeignKey
列对应于“一”侧的relationship
属性?
【问题讨论】:
【参考方案1】:一对多的关系是这样建立的:
class Group(Base):
id = Column(Integer, primary_key=True)
users = relationship(lambda: User)
class User(Base):
id = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey(Group.id))
SQLAlchemy 推断您打算使用 parent_id
作为 users
的连接条件,因为它是链接两个表的唯一外键。
如果你有循环关系:
class Group(Base):
id = Column(Integer, primary_key=True)
owner_id = Column(Integer, ForeignKey("users.id"))
users = relationship(lambda: User)
class User(Base):
id = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey(Group.id))
owned_groups = relationship(Group)
如果你尝试这个,它不会起作用,因为 SQLAlchemy 抱怨它无法推断每个关系使用什么外键。相反,您必须明确告诉它使用什么:
class Group(Base):
id = Column(Integer, primary_key=True)
owner_id = Column(Integer, ForeignKey("users.id"))
users = relationship(lambda: User, foreign_keys=lambda: User.parent_id)
class User(Base):
id = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey(Group.id))
owned_groups = relationship(Group, foreign_keys=Group.owner_id)
一个更完整的反向引用示例:
class Group(Base):
id = Column(Integer, primary_key=True)
owner_id = Column(Integer, ForeignKey("users.id"))
users = relationship(lambda: User, foreign_keys=lambda: User.parent_id, back_populates="parent")
owner = relationship(lambda: User, foreign_keys=owner_id, back_populates="owned_groups")
class User(Base):
id = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey(Group.id))
owned_groups = relationship(Group, foreign_keys=Group.owner_id, back_populates="owner")
parent = relationship(Group, foreign_keys=parent_id, back_populates="users")
【讨论】:
感谢您的回答。看来您最近一直在回答我的大部分问题...感谢您的帮助! 有趣的是,SQLAlchemy 会对您的中间示例感到困惑,因为每个类上最多只有一个外键。 (你帮助回答了我的直接问题,所以我会按原样接受答案,但我很好奇你能否详细说明 SQLAlchemy 究竟会混淆什么。) @wheresmycookie SQLAlchemy 无法确定这一点的原因是,不能随意假设所有关系都是一对多的。它们也可以是多对一的。我添加了一个带有 backrefs 的示例,应该可以清楚地说明这一点。在每一侧,实际上有两个关系对应于两个外键中的每一个。想象一下你是 SQLAlchemy。在第二个例子中,你怎么知道owned_groups
不应该是users
关系的另一端(因此使用parent_id
外键)?以上是关于SQLAlchemy 一对多关系澄清的主要内容,如果未能解决你的问题,请参考以下文章
Flask 学习-78.Flask-SQLAlchemy 一对多关系