SQLAlchemy和自引用对象的最佳实践

时间:2016-01-13 19:11:14

标签: python sqlalchemy

我的模型中有一个自引用数据结构。它可以描述为

class Example(Base):
    __tablename__ = 'example'
    id = Column(Integer, primary_key=True)
    title = Column(String(255))
    parent_id = Column(Integer, ForeignKey('example.id'), nullable=True)
    parent = relationship("Example")

我想在会话中创建一个包含一个或多个子节点的父节点。我的第一个方法是:

  1. 创建会话
  2. 更新/插入家长(session.merge
  3. 提交/关闭会话
  4. 创建新会话,加载父级,创建子级
  5. 设置child.parent_id = parent.id
  6. 提交/关闭会话
  7. 由于我希望将整个流程作为事务处理,因此我希望将其置于一个会话中。

    我的问题,如果我使用一个会话:

    设置child.parent = parent会导致TypeError:ypeError: Incompatible collection type: None is not list-like。设置child.parent_id = parent.id不起作用,因为parent.id尚未设置。

2 个答案:

答案 0 :(得分:1)

这里的relationship()工作方向相反,代表一个子项列表,而不是父项列表。

它的工作原理如下:

class Example(Base):
    __tablename__ = 'example'
    id = Column(Integer, primary_key=True)
    title = Column(String(255))
    parent_id = Column(Integer, ForeignKey('example.id'), nullable=True)
    children = relationship("Example")

然后您需要创建父记录并向其添加子记录:

    sql = sqldb.get_session()
    child1 = sqldb.system.Example()
    child1.title = 'child-test'
    sql.add(child1)

    child2 = sqldb.system.Example()
    child2.title = 'child-test2'
    sql.add(child2)

    parent = sqldb.system.Example()
    parent.title = 'parent-test'
    parent.children = [child1, child2]
    sql.add(parent)

    sql.commit()

答案 1 :(得分:-1)

class Example(Base):
    __tablename__ = 'example'
    id = Column(Integer, primary_key=True)
    title = Column(String(255))
    parent_id = Column(Integer, nullable=True)

尝试这样的事情,因为你只使用一张桌子,所以你不需要与自己建立关系。

你应该可以做类似

的事情
ex1 = Example(1,'test')
session.add(ex1)
ex2 = Example(2,'test2',1)
# or ex2 = Example(2,'test2',ex1.id)
session.add(ex2)

应该有效

如果你坚持关于各种触发器的关系(我通常更愿意让程序员负责,而不是数据库的灵活性问题)使用remote_side < / p>

class Example(Base):
    __tablename__ = "example"
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.Text, unique=True)
    parent_id = db.Column(Integer,db.ForeignKey('example.id'))
    children= relationship("Example",
                backref=backref('parent', remote_side=[id])
            )

这将创建邻接列表关系 有关详细信息,请参阅。

http://docs.sqlalchemy.org/en/improve_toc/orm/self_referential.html#adjacency-list-relationships