如何在 SQLAlchemy 中的关联对象中创建基于条目值的约束?

And*_*rra 2 python sqlalchemy

给出以下最小示例:

class Association(Base):
    __tablename__ = "association_table"
    left_id = Column(ForeignKey("left_table.id"), primary_key=True)
    right_id = Column(ForeignKey("right_table.id"), primary_key=True)
    first_child = Column(Boolean, nullable=False)
    child = relationship("Child", back_populates="parents")
    parent = relationship("Parent", back_populates="children")
class Parent(Base):
    __tablename__ = "left_table"
    id = Column(Integer, primary_key=True)
    children = relationship("Association", back_populates="parent")
class Child(Base):
    __tablename__ = "right_table"
    id = Column(Integer, primary_key=True)
    parents = relationship("Association", back_populates="child")
Run Code Online (Sandbox Code Playgroud)

如何限制只有一个孩子可以成为父母的第一个孩子?(忽略“夫妇第一个孩子”的逻辑)

van*_*van 6

最简单的解决方案是使用部分索引,PostgreSQL支持部分索引SQLite支持部分索引

下面的代码应该适用于两者:

class Association(Base):
    __tablename__ = "association_table"
    left_id = Column(ForeignKey("left_table.id"), primary_key=True)
    right_id = Column(ForeignKey("right_table.id"), primary_key=True)
    first_child = Column(Boolean, nullable=False)
    child = relationship("Child", back_populates="parents")
    parent = relationship("Parent", back_populates="children")

    __table_args__ = (
        Index(
            "uci_first_child",
            left_id,
            unique=True,
            postgres_where=first_child==True,  # will be used for postgresql
            sqlite_where=first_child==True,    # will be used for sqlite
        ),
    )
Run Code Online (Sandbox Code Playgroud)