简体   繁体   English

SQLAlchemy:单表邻接表Inheritance

[英]SQLAlchemy: Adjacency List with Single Table Inheritance

I am trying to setup the following single-table inheritance adjacency list structure, where the child object contains a relationship to the parent object:我正在尝试设置以下单表 inheritance 邻接列表结构,其中子 object 包含与父 object 的关系:

class Parent(Base):
    __tablename__ = 'testtable'
    type = Column(String)
    __mapper_args__ = {
        'polymorphic_on':type,
        'polymorphic_identity':'Parent'
    }

    id = Column(Integer, primary_key = True)

class Child(Parent):
    __mapper_args__ = {
        'polymorphic_identity':'Child'
    }

    parent_id = Column(Integer, ForeignKey('testtable.id'))
    parent = relationship('Parent')

However, when I try to create an object, of type Child, and set / append a parent object:但是,当我尝试创建子类型的 object 并将 / append 设置为父 object 时:

p = Parent()
c = Child()
c.parent.append(p)

db_session.add(c)
db_session.commit()

I get the following error:我收到以下错误:

UnmappedColumnError: Can't execute sync rule for destination column 'testtable.parent_id'; UnmappedColumnError:无法为目标列“testtable.parent_id”执行同步规则; mapper 'mapped class Parent->testtable' does not map this column. mapper 'mapped class Parent->testtable' 没有 map 此列。 Try using an explicit foreign_keys collection which does not include this column (or use a viewonly=True relation).尝试使用不包含此列的显式foreign_keys集合(或使用 viewonly=True 关系)。

I played around with different relationship definitions (backref etc.) but am pretty lost at this stage.我玩弄了不同的关系定义(backref 等),但在这个阶段我很迷茫。 Any ideas would be highly appreciated!任何想法将不胜感激!

Thanks a lot in advance非常感谢提前

For convenience, here is a full example:为方便起见,这里有一个完整的例子:

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String
from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship

Base = declarative_base()
Session = sessionmaker()

engine = create_engine('sqlite:///test.db')
Session.configure(bind = engine)
db_session = Session()

class Parent(Base):
    __tablename__ = 'testtable'
    type = Column(String)
    __mapper_args__ = {
        'polymorphic_on':type,
        'polymorphic_identity':'Parent'
    }

    id = Column(Integer, primary_key = True)

class Child(Parent):
    __mapper_args__ = {
        'polymorphic_identity':'Child'
    }

    parent_id = Column(Integer, ForeignKey(Parent.id))
    parent = relationship('Parent', remote_side=[parent_id])

Base.metadata.create_all(engine)

p = Parent()
c = Child()
c.parent.append(p)

db_session.add(c)
db_session.commit()

Your Child object has a single foreign key to Parent so it is a many-to-one relationship.您的Child object 对Parent有一个外键,因此它是多对一的关系。 Therefore you need to use c.parent = p instead of c.parent.append(p) .因此,您需要使用c.parent = p而不是c.parent.append(p) You also need to use remote_side=Parent.id to establish the relationship .您还需要使用remote_side=Parent.id来建立relationship

Working example:工作示例:

from sqlalchemy import create_engine, Column, Integer, String, ForeignKey
from sqlalchemy.orm import declarative_base, relationship, Session

Base = declarative_base()

engine = create_engine("sqlite://")


class Parent(Base):
    __tablename__ = "testtable"
    type = Column(String)
    __mapper_args__ = {
        "polymorphic_on": type,
        "polymorphic_identity": "Parent",
    }

    id = Column(Integer, primary_key=True)

    def __repr__(self):
        return f"<Parent(id={self.id})>"


class Child(Parent):
    __mapper_args__ = {"polymorphic_identity": "Child"}

    parent_id = Column(Integer, ForeignKey(Parent.id))
    parent = relationship("Parent", remote_side=Parent.id)

    def __repr__(self):
        return f"<Child(id={self.id}, parent_id={self.parent_id})>"


Base.metadata.create_all(engine)

with Session(engine) as db_session:
    p = Parent()
    c = Child()
    c.parent = p
    db_session.add(c)
    db_session.commit()
    print(c)  # <Child(id=2, parent_id=1)>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM