Вы не создаете отношения между внуками и родителями.
Отношения между внуком и родителем не подразумеваются в вашей модели данных; родитель ребенка автоматически не становится родителем всех внуков ребенка.
Вы должны определить это отношение явно, то есть добавить его в GrandChild
:
class GrandChild(Base):
[...]
parent = relationship("Parent")
и затем создайте отношение на экземплярах:
gc1.parent = p3
gc2.parent = p3
gc3.parent = p3
gc4.parent = p3
Это добавит записи соответственно:
sqlalchemy.engine.base.Engine INSERT INTO grandchild (name, parent_id, child_id) VALUES (?, ?, ?)
sqlalchemy.engine.base.Engine ('gc1', 1, 1)
[...]
Однако, поскольку отношения родитель-потомок в вашей модели данных не предполагают каких-либо отношений внука-родителя, вы можете создать родителя без детей, у которого есть внуки.
sink = Parent(name="SINK")
gc1.parent = sink
print("Name: {}, Parent: {}, Parent.children: {}, Child.parent: {}"
.format(gc1.name, gc1.parent.name, gc1.parent.children, gc1.grandparent.parents.name))
# Name: gc1, Parent: SINK, Parent.children: [], Child.parent: P3
Основываясь на моем понимании трехуровневого отношения, я не могу придумать случай использования где-либо. как это найти приложение.
Если вам нужны неявные и непротиворечивые отношения между родителем и внуком через ребенка, отбросьте прямые отношения между родителем и внуком:
class Parent(Base):
__tablename__ = 'parent'
id = Column(Integer, primary_key=True)
name = Column(String)
children = relationship("Child", back_populates="parent")
def __repr__(self):
return "{}(name={})".format(self.__class__.__name__, self.name)
class Child(Base):
__tablename__ = 'child'
id = Column(Integer, primary_key=True)
name = Column(String)
parent_id = Column(Integer, ForeignKey('parent.id'))
parent = relationship("Parent", back_populates="children")
children = relationship("GrandChild", back_populates="parent")
# same __repr__()
class GrandChild(Base):
__tablename__ = 'grandchild'
id = Column(Integer, primary_key=True)
name = Column(String)
child_id = Column(Integer, ForeignKey('child.id'))
parent = relationship("Child", back_populates="children")
# same __repr__()
p3 = Parent(name="P3")
c5 = Child(name="C5")
gc1 = GrandChild(name="gc1")
p3.children = [c5]
c5.children = [gc1]
Вы можете получить доступ к дедушке и внуку через:
print(gc1.parent.parent)
# Parent(name=P3)
И наоборот, немного более утомительно из-за двух отношений один-ко-многим в иерархии:
for child in p3.children:
for gc in child.children:
print(p3, child, gc)
# Parent(name=P3) Child(name=C5) GrandChild(name=gc1)