SQLAlchemy一对多关系澄清

whe*_*kie 3 sqlalchemy

阅读 SQLAlchemy 文档后,我仍然不清楚实际上应该如何指定一对多关系。我将分解文档并解释为什么我感到困惑(http://docs.sqlalchemy.org/en/latest/orm/basic_relationships.html#one-to-many):

一对多关系在引用父表的子表上放置一个外键。

看起来我要Column在模型上放置一些属性,该属性将位于关系的“多”端。

然后在父级上指定关系(),作为引用由子级表示的项目集合:

这意味着父级上有一些属性指定参与关系“多”方的模型。

如果不是因为可能存在这样一种情况,即我想要定义两个一对多关系,并且关系双方的相同参与者,这对我来说是完全有意义的。

SQLAlchemy 如何知道ForeignKey关系“多”侧的列对应于relationship“一”侧的属性?

uni*_*rio 6

一对多关系的建立如下:

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))
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)

如果您尝试这样做,它将不起作用,因为 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)
Run Code Online (Sandbox Code Playgroud)

带有 backrefs 的更完整的示例:

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")
Run Code Online (Sandbox Code Playgroud)