【问题标题】:can't insert into one-to-many relationship in sqlalchemy无法在 sqlalchemy 中插入一对多关系
【发布时间】:2013-08-18 17:25:07
【问题描述】:

我在 sqlalchemy 中有一对多的关系,但我没有让插入正常工作。我试图在这里做一个最小的例子:

from sqlalchemy import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, sessionmaker

db = create_engine('sqlite://')
db.echo = True

metadata = MetaData(db)
Base = declarative_base()
Session = sessionmaker(bind=db)
session = Session()

class Child(Base):
    __table__ = Table('child', Base.metadata,
        Column('id', Integer, primary_key=True),
        Column('parent_id', Integer),
        Column('name', String(50))
    )

class Parent(Base):
    __table__ = Table('parent', Base.metadata,
        Column('id', Integer, primary_key=True),
        Column('name', String(50))
    )

    children = relationship(Child, primaryjoin="Parent.id == Child.parent_id",
                            foreign_keys=[__table__.c.id])



Base.metadata.create_all(db)

c = Child(id=1, name="C")
p = Parent(id=1, name="P", children=[c])
session.add(p)
session.commit()

运行它会从session.add(p) 得到AttributeError: 'list' object has no attribute '_sa_instance_state'

我尝试将类更改为:

class Child(Base):
    __tablename__ = 'child'

    id = Column('id', Integer, primary_key=True)
    parent_id = Column('parent_id', Integer, ForeignKey('parent.id'))
    name = Column('name', String(50))

class Parent(Base):
    __tablename__ = 'parent'

    id = Column('id', Integer, primary_key=True)
    name = Column('name', String(50))

    children = relationship(Child, backref="parent")

然后它就可以工作了。我在那里指定 parent_id 是一个外键并使用 backref 语法。但是在我的生产代码中,父表是一个临时表,所以我不能使用外键直接引用它。那么第一个代码块有什么问题,如何解决?

【问题讨论】:

    标签: python sqlalchemy


    【解决方案1】:

    来自docs 中的 SQLAlchemy relationship API:

    也就是说,如果这个relationship()的primaryjoin条件是a.id == b.a_id,并且b.a_id中的值要求a.id中存在,那么“外键”列这个 relationship() 是 b.a_id。

    在您的示例中,child.parent_id 必须出现在 parent.id 中。所以你的“外键”栏是child.parent_id

    因此,改变:

    foreign_keys=[__table__.c.id]
    

    到这里:

    foreign_keys=[Child.__table__.c.parent_id]
    

    应该可以解决你的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-22
      • 1970-01-01
      • 2013-06-04
      • 2013-05-02
      • 1970-01-01
      • 2016-04-04
      • 2020-03-23
      • 1970-01-01
      相关资源
      最近更新 更多