如何在SQLAlchemy多态父类与子类间创建复合索引
解决SQLAlchemy多态子类复合索引无法被Alembic Autogenerate识别的问题
核心原因
单表继承模式下,子类没有独立的数据库表,所有字段共享父类的main表。Alembic的autogenerate仅扫描**父类的__table_args__**以及表对象绑定的索引,直接在子类中定义的Index实例不会被检测到;同时子类无法使用__table_args__,因为它没有关联的__table__属性。
解决方案
将子类专属的复合索引定义到父类的__table_args__中。单表继承时子类的bid字段会被自动添加到父类的main表,因此可以直接在父类中引用该字段名创建索引。
修改后的代码
from sqlalchemy import Column, String, ForeignKey, Index, func from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() SomeMixin = ... # 你的Mixin类 class Main(Base, SomeMixin): __tablename__ = "main" __table_args__ = ( # 原有约束和索引 Index( "ix_main_bid_mtype", "bid", "mtype", ), ) id = Column(String, primary_key=True, default=func.generate_object_id()) mtype = Column(String, nullable=False) __mapper_args__ = {"polymorphic_on": mtype} class SubClass(Main): __mapper_args__ = {"polymorphic_identity": "subclass"} bid = Column(String, ForeignKey("other.id", ondelete="CASCADE"))
验证效果
运行Alembic autogenerate命令:
alembic revision --autogenerate -m "Add bid-mtype composite index for SubClass"
生成的迁移代码会与你期望的一致:
def upgrade(): # ### commands auto generated by Alembic - please adjust! ### op.create_index( "ix_main_bid_mtype", "main", ["bid", "mtype"], unique=False, ) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### op.drop_index(op.f("ix_main_bid_mtype"), table_name="main") # ### end Alembic commands ###
补充说明
如果需要明确标记索引属于子类,可以在索引旁添加注释:
__table_args__ = ( # 原有约束和索引 Index( "ix_main_bid_mtype", "bid", "mtype", comment="Composite index for SubClass records (bid + mtype)" ), )
内容的提问来源于stack exchange,提问作者Gaëtan GOUSSEAUD
相关产品推荐
相关产品推荐

