Python + SqlAlchemy:当父子都是新建时添加父子记录

2024-01-12

我问过一个类似的问题 https://stackoverflow.com/q/59097167/2144390已经,但我认为如果我不提供我已经编码的示例,而是简单地陈述我的案例的目标,那么会更清楚。开始:

我有一个处于自引用一对多关系的表。即,它是经典父/子设置中的分层表。没什么特别的,只是一个基本的父母有很多孩子,孩子有一个父母。

我可以在 ORM 中很好地创建表。然而,从那里,我想使用 JSON 文件中的数据加载表。当然,我的 JSON 表示存在顶级“父”条目,每个条目都有 n 个“子”,并且每个条目都有子,等等。对于所有这些子记录,我显然无法引用特定的“parent.id”,因为父项尚未保留在数据库中。而且,显然,在任何情况下,我想要添加一个全新的父/子记录图(即,不仅仅是从 JSON 加载示例),这个问题都存在。

在实体框架中完成这一壮举一直非常简单。只要正确定义了关系,就可以简单地works,记录添加的所有正确顺序。

在 SqlAlchemy 中,这似乎也是完全可能的,但是(我认为)我定义关系的方式有问题。到目前为止我尝试过的任何方式,我得到的是这个错误:

Class 'MyTableClass' is mapped, but this instance lacks instrumentation. This occurs when the instance is created before sqlalchemy.orm.mapper(MyTableClass) was called.

我不知道如何准确地阅读它,但我认为它告诉我的是它试图在创建父对象之前创建子对象。但我不知道,这也无助于我发现我的人际关系哪里不明确。

任何指导表示赞赏!


根据以下人士的回答和评论这个问题 https://stackoverflow.com/q/2638217/2144390以下似乎对我有用:

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

connection_url = "mssql+pyodbc://@localhost,49242/myDb?driver=ODBC+Driver+17+for+SQL+Server"
engine = create_engine(connection_url)

Base = declarative_base()


class Person(Base):
    __tablename__ = 'person'

    id = Column(Integer, autoincrement=True, primary_key=True)
    name = Column(String(50))
    _parent_id = Column(Integer, ForeignKey('person.id'))
    parent = relation('Person', remote_side=[id])
    children = relation('Person', remote_side=[_parent_id], uselist=True)

    def __repr__(self):
        return f"<Person(id={self.id}, name='{self.name}'>)"


Base.metadata.drop_all(engine, checkfirst=True)
Base.metadata.create_all(engine)

Session = sessionmaker(bind=engine)
session = Session()

parent = Person(name='Homer')
child = Person(name='Bart')
parent.children.append(child)
child = Person(name='Lisa')
parent.children.append(child)

print(f"{parent.name}'s (unpersisted) children: {parent.children}")
# Homer's (unpersisted) children: [<Person(id=None, name='Bart'>), <Person(id=None, name='Lisa'>)]

session.add(parent)
session.commit()

print(f"{parent.name}'s (persisted) children: {parent.children}")
# Homer's (persisted) children: [<Person(id=2, name='Bart'>), <Person(id=3, name='Lisa'>)]

child = session.query(Person).filter(Person.name=='Lisa').first()
print(f"{child.name}'s parent: {child.parent}")
# Lisa's parent: <Person(id=1, name='Homer'>)

with engine.begin() as conn:
    print(conn.execute("SELECT * FROM person").fetchall())
    # [(1, 'Homer', None), (2, 'Bart', 1), (3, 'Lisa', 1)]
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python + SqlAlchemy:当父子都是新建时添加父子记录 的相关文章

随机推荐