我有两个表,
foo
和 bar
,我希望 foo.bar_id
链接到 bar
。问题是这是一种单向的一对一关系。 bar
一定对foo
一无所知。对于每一个 foo,都会有且只有一个 bar
。
理想情况下,选择 foo 后,我可以这样做:
myfoo.bar.whatever = 5
如何实现这一点?
文档很好地解释了这一点:
class Parent(Base):
__tablename__ = 'parent'
id = Column(Integer, primary_key=True)
child = relationship("Child", uselist=False, backref="parent")
class Child(Base):
__tablename__ = 'child'
id = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey('parent.id'))
或
class Parent(Base):
__tablename__ = 'parent'
id = Column(Integer, primary_key=True)
child_id = Column(Integer, ForeignKey('child.id'))
child = relationship("Child", backref=backref("parent", uselist=False))
class Child(Base):
__tablename__ = 'child'
id = Column(Integer, primary_key=True)
注意:自答案编写以来,API 和相关文档已经发生了很大变化。 新文档
如果您想要真正的一对一关系,您还必须在关系定义中使用“uselist=False”。
bar_id = Column(Integer, ForeignKey(Bar.id))
bar = relationship(Bar, uselist=False)
我认为如果它是真正的一对一关系,我们应该为外键添加唯一性约束,以便另一个父级不能有其他父级子级!像这样:
class Parent(Base):
__tablename__ = 'parent'
id = Column(Integer, primary_key=True)
child_id = Column(Integer, ForeignKey('child.id'), unique=True)
child = relationship("Child", backref=backref("parent", uselist=False))
class Child(Base):
__tablename__ = 'child'
id = Column(Integer, primary_key=True)
事实证明这实际上很简单。在你的 Foo 模型中:
bar_id = Column(Integer, ForeignKey(Bar.id))
bar = relationship(Bar)
使用
uselist=False
的其他答案是正确的,但在 SQLAlchemy 2.0 中,如果您的 relationship
注释使用非集合类型,Mapped
现在足够聪明,可以推断出它。
来自文档:
2.0 版新增功能:
构造可以从给定的relationship()
注释导出relationship.uselist
参数的有效值。Mapped
这是针对 SqlAlchemy 2.0 修改的 chadwick.boulay 的代码:
class Parent(Base):
__tablename__ = 'parent'
id: Mapped[int] = mapped_column(Integer(), primary_key=True)
child: Mapped["Child"] = relationship("Child", backref="parent")
class Child(Base):
__tablename__ = 'child'
id: Mapped[int] = mapped_column(Integer(), primary_key=True)
parent_id: Mapped[int] = mapped_column(Integer(), ForeignKey('parent.id'))
注意
child
如何用Mapped["Child"]
注释,即child
是一个Child
。如果你想使用一对多关系,你可以将其注释为列表:
children: Mapped[List["Child"]] = relationship("Child", backref="parent")