我发现如果单表继承设置中的子类中存在__table_args__
,则SQLAlchemy会抛出sqlalchemy.exc.ArgumentError: Can't place __table_args__ on an inherited class with no table
。同时,可以在子类上定义一个index=True
的列,它以与__table_args__
相同的方式更改父表。
这是我的设置:
import sqlalchemy as sa
import sqlalchemy.ext.declarative
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class A(Base):
__tablename__ = 'a'
id = sa.Column(sa.Integer, primary_key=True)
type = sa.Column(sa.Text, nullable=False)
__mapper_args__ = {
'polymorphic_on': type,
}
class B(A):
b = sa.Column(sa.Integer, index=True)
__mapper_args__ = {
'polymorphic_identity': 'b',
}
class C(A):
c = sa.Column(sa.Integer)
__mapper_args__ = {
'polymorphic_identity': 'c',
}
__table_args__ = (
sa.Index('ix_test', c),
)
engine = sa.engine.create_engine("sqlite://", echo=True)
Base.metadata.create_all(engine)
session = sa.orm.Session(engine)
session.add_all([
B()
])
session.commit()
print(session.query(A))
它抛出:
Traceback (most recent call last):
File "test.py", line 29, in <module>
class C(A):
File "/home/andrei/projects/my_project/.tox/dev/lib/python3.5/site-packages/sqlalchemy/ext/decla
rative/api.py", line 64, in __init__
_as_declarative(cls, classname, cls.__dict__)
File "/home/andrei/projects/my_project/.tox/dev/lib/python3.5/site-packages/sqlalchemy/ext/decla
rative/base.py", line 88, in _as_declarative
_MapperConfig.setup_mapping(cls, classname, dict_)
File "/home/andrei/projects/my_project/.tox/dev/lib/python3.5/site-packages/sqlalchemy/ext/decla
rative/base.py", line 103, in setup_mapping
cfg_cls(cls_, classname, dict_)
File "/home/andrei/projects/my_project/.tox/dev/lib/python3.5/site-packages/sqlalchemy/ext/decla
rative/base.py", line 133, in __init__
self._setup_inheritance()
File "/home/andrei/projects/my_project/.tox/dev/lib/python3.5/site-packages/sqlalchemy/ext/decla
rative/base.py", line 442, in _setup_inheritance
"Can't place __table_args__ on an inherited class "
sqlalchemy.exc.ArgumentError: Can't place __table_args__ on an inherited class with no table.
有人知道任何变通方法吗?
答案 0 :(得分:4)
指数可以放在表格定义之外。
class C(A):
c = sa.Column(sa.Integer)
__mapper_args__ = {
'polymorphic_identity': 'c',
}
Index('ix_test', C.c)
答案 1 :(得分:0)
我在更新到SQLAlchemy 2.3后开始出现此错误。
如果您可以删除表参数,它将起作用(但可能会抱怨其他事情,特别是如果两个子类共享一个字段名称 - 这对我来说是__table_args__ = {'extend_existing': True}
。
最后,解决方法是明确指定子类上的表名,例如:
class Establishment(Model):
__tablename__ = 'establishments'
name = Column(String(32))
class Cafe(Establishment):
__mapper_args__ = {'polymorphic_identity': 'cafe'}
coffee_type = Column(String(32))
class Bar(Establishment):
__tablename__ = 'establishments'
__table_args__ = {'extend_existing': True}
__mapper_args__ = {'polymorphic_identity': 'bar'}
alcohol_license_number = Column(String(40))
bar_type = Column(Enum(BarType)) # defined elsewhere
class Restaurant(Establishment):
__tablename__ = 'establishments'
__table_args__ = {'extend_existing': True}
__mapper_args__ = {'polymorphic_identity': 'bar'}
alcohol_license_number = Column(String(40))
cuisine_list = Column(String(255))
一个粗略的例子,但希望这个想法有意义 - 餐厅和酒吧都有一个字段来保存他们的酒类许可证信息,所以我们希望这两个人使用表中的现有字段而不是冲突 - 现在我们必须指定tablename自SQLAlchemy 2.3。
我知道这个例子与问题(关于索引)的问题不完全相同,但它会导致同样的错误,这个解决方案应该适用于这种情况。