SQLAlchemy:复合主键的多个外键指向同一表

6 投票
2 回答
7045 浏览
提问于 2025-04-17 10:18

在SQLAlchemy中,假设我们有一个叫做Foo的表,它有一个复合主键,还有一个叫Bar的表,它有两个外键约束,分别链接到Foo(也就是说,每个Bar都有两个Foo的对象)。

我遇到的问题是关于relationship这个函数,它让我在primaryjoin中重复一些信息,而这些信息我已经在ForeignKeyConstraint中提供过了(这违反了“不要重复自己”的原则)。有没有其他方法可以组织这些内容,这样我就不需要重复信息了?有没有办法把相关的ForeignKeyConstraint传递给relationship

class Foo(Base):
    __tablename__ = "Foo"
    id_1 = Column(Integer, primary_key=True)
    id_2 = Column(Integer, primary_key=True)

class Bar(Base):
    __tablename__ = "Bar"
    id = Column(Integer, primary_key=True)

    foo_1_id_1 = Column(Integer)
    foo_1_id_2 = Column(Integer)

    foo_2_id_1 = Column(Integer)
    foo_2_id_2 = Column(Integer)

    __table_args__ = (
            ForeignKeyConstraint(
                [foo_1_id_1,foo_1_id_2],
                [Foo.id_1,Foo.id_2]
                ),
            ForeignKeyConstraint(
                [foo_2_id_1,foo_2_id_2],
                [Foo.id_1,Foo.id_2]
                )
            )

    foo_1 = relationship(Foo,primaryjoin="(Bar.foo_1_id_1 == Foo.id_1) & (Bar.foo_1_id_2 == Foo.id_2)")
    foo_2 = relationship(Foo,primaryjoin="(Bar.foo_2_id_1 == Foo.id_1) & (Bar.foo_2_id_2 == Foo.id_2)")

谢谢。

2 个回答

1

你还可以使用 foreign_keys 和一系列外键。

可以查看 多个连接路径 的相关内容。

foo_1 = relationship(Foo, foreign_keys=[foo_1_id_1, foo_2_id_2])
foo_2 = relationship(Foo, foreign_keys=[foo_2_id_1, foo_2_id_2])
2

relationship()这个东西,自己不能完全搞定所有的设置。特别是当有多种方式可以指向相关的表时,这种情况就会出现。
在你的例子中,看起来sqlalchemy好像能通过列的名字来猜测,但实际上它并不能这样做,也不应该这样做。

虽然你可能觉得信息有点重复,但其实你只是对你的关系配置更加具体而已。

实际上,你可以在relationship()的设置中指定foreign_keys,不过现在这个选项的用途有点不同,所以你还是需要配置primaryjoin

撰写回答