【发布时间】:2016-10-14 20:49:55
【问题描述】:
由于sqlalchemy.orm.relationship() 已经暗示了关系,我不想在 db 中创建约束。我该怎么办?
目前我在 alembic 迁移后手动删除这些约束。
【问题讨论】:
标签: python orm sqlalchemy foreign-keys
由于sqlalchemy.orm.relationship() 已经暗示了关系,我不想在 db 中创建约束。我该怎么办?
目前我在 alembic 迁移后手动删除这些约束。
【问题讨论】:
标签: python orm sqlalchemy foreign-keys
而不是定义“模式”级别ForeignKey 约束创建custom foreign condition;将您想用作“外键”的列和primaryjoin 传递给relationship。您必须手动定义primaryjoin,因为:
默认情况下,该值是根据父子表(或关联表)的外键关系计算得出的。
In [2]: class A(Base):
...: a_id = Column(Integer, primary_key=True)
...: __tablename__ = 'a'
...:
In [3]: class C(Base):
...: c_id = Column(Integer, primary_key=True)
...: a_id = Column(Integer)
...: __tablename__ = 'c'
...: a = relationship('A', foreign_keys=[a_id],
...: primaryjoin='A.a_id == C.a_id')
...:
也可以使用foreign() 在primaryjoin 中内联注释外键:
a = relationship('A', primaryjoin='foreign(C.a_id) == A.a_id')
您可以验证没有为表 c 发出FOREIGN KEY 约束:
In [4]: from sqlalchemy.schema import CreateTable
In [5]: print(CreateTable(A.__table__))
CREATE TABLE a (
a_id INTEGER NOT NULL,
PRIMARY KEY (a_id)
)
In [6]: print(CreateTable(C.__table__))
CREATE TABLE c (
c_id INTEGER NOT NULL,
a_id INTEGER,
PRIMARY KEY (c_id)
)
警告:
请注意,如果没有在 DB 端设置 FOREIGN KEY 约束,您可以按照您想要的任何方式将您的引用完整性分解成碎片。在 ORM/应用程序级别存在关系,但无法在 DB 中强制执行。
【讨论】:
relationship 是一个 ORM 概念,有助于将 SQL 表关系映射到对象世界,但它没有定义它们。
A.a_id 绑定到C.a_id (a_id = Column(Integer, ForeignKey('C.a_id'), primary_key=True)) 的正确方法吗?
ForeignKey 在 DB 模式中定义了一个约束。外键约束有助于维护完整性;它可以防止您插入 a_id 和 A 中不存在的 C,并且还可以定义在更改 A 时应该发生的级联操作 - 通常被删除。另一方面,relationship 定义了对象的关联方式。它可以并且经常确实使用 DB 模式外键约束信息来确定键列是什么,但正如这里所见,它并不是严格要求的。 relationship 还提供了定义 Python 中应该发生的事情的级联行为。
relationship 属性,例如在 ORM 的对象端仅列出过去的事件等。一个简单的外键约束本身并不能建模,它只是强制执行键完整性。