In my application I have an entity that is part of a many to many relationship. However I want to define the ==
method on that entity. But when I reference the children I get the error
Traceback (most recent call last):
File "C:/Users/user/workspace/app/tmp.py", line 61, in <module>
print(p == p1)
File "C:/Users/user/workspace/app/tmp.py", line 18, in __eq__
return self.id == o.id and self.children == o.children
File "C:\Users\user\.virtualenvs\websocketserver-QkEQJFtA\lib\site-packages\sqlalchemy\orm\attributes.py", line 282, in __get__
return self.impl.get(instance_state(instance), dict_)
File "C:\Users\user\.virtualenvs\websocketserver-QkEQJFtA\lib\site-packages\sqlalchemy\orm\attributes.py", line 710, in get
value = self.callable_(state, passive)
File "C:\Users\user\.virtualenvs\websocketserver-QkEQJFtA\lib\site-packages\sqlalchemy\orm\strategies.py", line 707, in _load_for_state
raise orm_exc.DetachedInstanceError(
sqlalchemy.orm.exc.DetachedInstanceError: Parent instance <Parent at 0x189b95446a0> is not bound to a Session; lazy load operation of attribute 'children' cannot proceed (Background on this error at: http://sqlalche.me/e/bhk3)
The App code looks like this.
from sqlalchemy import Column, Integer, ForeignKey, create_engine, Boolean
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, sessionmaker
Base = declarative_base()
class Parent(Base):
__tablename__ = 'parent'
id = Column(Integer, primary_key=True)
children = relationship("Association", back_populates="parent", lazy='select')
def __repr__(self):
return f"<Parent(id='{self.id}', children='{self.children}')>"
def __eq__(self, o: object) -> bool:
self.children # <--- crashes when referencing self.children
if isinstance(o, Parent):
return self.id == o.id and self.children == o.children
return False
class Child(Base):
__tablename__ = 'child'
id = Column(Integer, primary_key=True)
parents = relationship("Association", back_populates="child", cascade="all, delete", lazy='select')
def __repr__(self):
return f"<Widget(id='{self.id}', parents='{self.parents}')>"
class Association(Base):
__tablename__ = 'association'
active = Column(Boolean, nullable=False)
child_id = Column(Integer, ForeignKey('child.id'), primary_key=True)
parent_id = Column(Integer, ForeignKey('parent.id'), primary_key=True)
parent = relationship("Parent", back_populates="children", lazy='select')
child = relationship("Child", back_populates="parents", lazy='select')
def __repr__(self):
return f"<Association(child_id='{self.child_id}', parent_id='{self.parent_id}',)> "
engine = create_engine("sqlite://")
SessionLocal = sessionmaker(bind=engine, autocommit=False, expire_on_commit=False)
Base.metadata.create_all(engine)
session = SessionLocal()
p = Parent()
session.add(p)
session.commit()
session.close()
session = SessionLocal()
p1 = session.query(Parent).filter(Parent.id == 1).first()
print(p1)
print(p1.children)
print(p == p1)
Why can I access the children using p1.children
or inside the __repr__
but not inside __eq__
?