dpw*_*pwr 4 python sql sqlalchemy foreign-keys
我正在尝试解决一个带有连接表继承的自引用表的问题,其中有一个外键链接继承关系,但也有一个类具有对其父实例的附加引用的情况。最好用一个简化的例子:
B 类继承自 A 类。B 类通过 B 类中的外键通过 id 列链接到 A 类。B 类还有一个列 ( a_id) 引用了与继承无关的 A 类。
from sqlalchemy import Column, Integer,ForeignKey, create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship, backref
Base = declarative_base()
class A(Base):
__tablename__ = 'a'
satype = Column(String(50))
__mapper_args__ = {
'polymorphic_identity': 'a',
'polymorphic_on': satype
}
id = Column(Integer, primary_key=True)
class B(A):
__tablename__ = 'b'
id = Column(Integer, ForeignKey('a.id'), primary_key=True)
__mapper_args__ = {
'polymorphic_identity': 'b'
}
a_id = Column(Integer, ForeignKey('a.id'))
a = relationship('A', backref='b')
engine = create_engine('sqlite:///:memory:', echo=True)
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
Run Code Online (Sandbox Code Playgroud)
根据文档,我将通过明确指定要使用的关系来解决表之间存在多个外键的情况。
class B(A):
__tablename__ = 'b'
id = Column(Integer, ForeignKey('a.id'), primary_key=True)
__mapper_args__ = {
'polymorphic_identity': 'b'
}
a_id = Column(Integer, ForeignKey('a.id'))
# I know the primaryjoin is no longer needed in SA >= 0.8
a = relationship('A', backref='b', foreign_keys=[a_id], primaryjoin=a_id==A.id)
Run Code Online (Sandbox Code Playgroud)
我认为问题在于我似乎无法弄清楚如何对多态列做同样的事情,id因为我没有明确定义这种关系。
感谢 SA 谷歌群组中的 Michael Bayer 提供了这个答案:
“相互依赖的外键”文档并不真正适用于这种情况。这里发生的是 B(A) 需要一个从 B 到 A 的连接,然后 Ba 需要一个不同的连接。尽管这里的约定清楚地说明了哪个外键约束是哪个,映射器仍然需要明确说明它们,就像这样:
class B(A):
__tablename__ = 'b'
id = Column(Integer, ForeignKey('a.id'), primary_key=True)
__mapper_args__ = {
'polymorphic_identity': 'b',
'inherit_condition': id == A.id
}
a_id = Column(Integer, ForeignKey('a.id'))
a = relationship(
'A',
backref='b', primaryjoin=A.id == a_id, remote_side=A.id)
Run Code Online (Sandbox Code Playgroud)