I am trying to resolve a problem with a self-referential table with Joined Table Inheritance where there is a foreign key linking the inheritance relationships, but then also a case where a class has an additional reference to an instance of its parent. Best to go with a simplified example:
Class B inherits from Class A. Class B is linked to Class A by the id column through the Foreign Key in Class B. Class B also has a column ( a_id
) which references Class A which has nothing to do with the inheritance.
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()
As per the documentation , I would resolve the case where there are multiple ForeignKeys between tables by explicitly specifying in the relationship which was to be used.
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)
I think the problem is that I don't seem to be able to figure out how to do the same for the polymorphic column id
as I am not explicitly defining that relationship.
Thanks to Michael Bayer in the SA google groups for this answer:
The "mutually dependent foreign keys" document doesn't really apply to this case. What happens here is that B(A) requires a join from B to A, and then Ba requires a different one. Even though the conventions here make it clear which foreign key constraint is which, the mapper still needs them to be explicitly spelled out, that's like this:
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)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.