如何使用声明式创建一对一关系

问题描述 投票:0回答:5

我有两个表,

foo
bar
,我希望
foo.bar_id
链接到
bar
。问题是这是一种单向的一对一关系。
bar
一定对
foo
一无所知。对于每一个 foo,都会有且只有一个
bar

理想情况下,选择 foo 后,我可以这样做:

myfoo.bar.whatever = 5 

如何实现这一点?

sqlalchemy
5个回答
148
投票

文档很好地解释了这一点

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 和相关文档已经发生了很大变化。 新文档


59
投票

如果您想要真正的一对一关系,您还必须在关系定义中使用“uselist=False”。

bar_id = Column(Integer, ForeignKey(Bar.id))
bar = relationship(Bar, uselist=False)

12
投票

我认为如果它是真正的一对一关系,我们应该为外键添加唯一性约束,以便另一个父级不能有其他父级子级!像这样:

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)

3
投票

事实证明这实际上很简单。在你的 Foo 模型中:

bar_id = Column(Integer, ForeignKey(Bar.id))
bar = relationship(Bar)

1
投票

使用

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")
© www.soinside.com 2019 - 2024. All rights reserved.