【问题标题】:Polymorphic self referential foreign key in sqlalchemysqlalchemy 中的多态自引用外键
【发布时间】:2015-10-02 08:01:50
【问题描述】:

我正在尝试解决具有联接表继承的自引用表的问题,其中存在链接继承关系的外键,但还有一个类具有对其父实例的附加引用的情况。最好用一个简化的例子:

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()

根据the documentation,我将通过明确指定要使用的关系来解决表之间存在多个 ForeignKey 的情况。

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)

我认为问题在于我似乎无法弄清楚如何对多态列 id 做同样的事情,因为我没有明确定义这种关系。

【问题讨论】:

    标签: python sql sqlalchemy foreign-keys


    【解决方案1】:

    感谢 SA google 小组中的 Michael Bayer 的回答:

    “相互依赖的外键”文档并不真正适用于 这个案例。这里发生的是 B(A) 需要从 B 连接到 A,然后 B.a 需要一个不同的。尽管约定俗成 这里明确哪个外键约束是哪个,mapper 仍然需要明确拼写出来,就像这样:

    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)
    

    【讨论】:

    • 我正面临这个问题。感谢您发布 Mike 的回复!
    猜你喜欢
    • 2017-05-15
    • 1970-01-01
    • 2021-06-15
    • 2014-01-16
    • 2021-07-02
    • 2019-07-02
    • 2014-09-30
    • 2019-11-24
    • 1970-01-01
    相关资源
    最近更新 更多