sqlalchemy joinload не связывает дочерний элемент с родительским. parent.childen [0] .parent не загружен - PullRequest
0 голосов
/ 28 апреля 2020

моя модель проста. у ребенка есть родитель. у родителя есть дети.

Parent
      Child

Я использую этот запрос для объединения

q = session.query(Parent).options(joinedload(Parent.children))

Я также использую session.expire_on_commit=False, потому что мне нужно получить доступ к объектам вне области сеанса.

Проблема в том, что когда я ссылаюсь на родителя от ребенка, родитель не загружается:

parent.children[0].parent # this raises error outside session scope. 

Ошибка заключается в следующем:

Parent instance <Parent at 0x117d95310> is not bound to a Session; lazy load operation of attribute 'parent' cannot proceed 

Как я могу решить эту проблему? (Я ожидал, что sqlalchemy связывает дочерний элемент с родительским при объединенной загрузке)


Отредактировано, чтобы добавить пример:

class Parent(Base):
    __tablename__ = 'parent'
    id = Column(Integer, primary_key=True)
    children = relationship("Child", back_populates="parent")

class Child(Base):
    __tablename__ = 'child'
    id = Column(Integer, primary_key=True)
    parent_id = Column(Integer, ForeignKey('parent.id'))
    parent = relationship("Parent", back_populates="children")

from contextlib import contextmanager

@contextmanager
def session_scope():
    """Provide a transactional scope around a series of operations."""
    session = Session()
    try:
        yield session
        session.commit()
    except:
        session.rollback()
        raise
    finally:
        session.close()

Затем я создаю несколько объектов:

with session_scope() as session:
    p = Parent()
    ch1 = Child()
    ch1.parent=p
    ch2 = Child()
    ch2.parent=p
    session.add(p)
    session.add(ch1)
    session.add(ch2)

затем я запрашиваю родителей с joinload детей и устанавливаю expire_on_commit в False:

with session_scope() as session:
    session.expire_on_commit = False
    p_all = session.query(Parent).options(subqueryload(Parent.children)).all()

, он работает, когда я запрашиваю детей родительского элемента:

p_all[0].children # -> [<__main__.Child at 0x10a857810>, <__main__.Child at 0x10ba89e10>]
p_all[0].children[0] # -> <__main__.Child at 0x10a857810>

, но затем я хочу получить доступ к родитель через ребенка и выдает ошибку:

p_all[0].children[0].parent # -> Error
# DetachedInstanceError: Parent instance <Child at 0x10a857810> is not bound to a Session; lazy load operation of attribute 'parent' cannot proceed 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...