0

I have two models:

class A(Base):
  __tablename__ = 'a'

  id = sa.Column(sa.Integer(), primary_key=True)


class B(Base):
  __tablename__ = 'b'

  id = sa.Column(sa.Integer(), primary_key=True)
  a_id = sa.Column(sa.Integer(), sa.ForeignKey(A.id))
  a = relationship(A)

Now if i fetch an object from B and query its a property with b.a, i get the error

sqlalchemy.exc.MissingGreenlet: greenlet_spawn has not been called; can't call await_only() here. Was IO attempted in an unexpected place? (Background on this error at: https://sqlalche.me/e/14/xd2s)

Putting var = b.a inside an async with session.begin(): block, or calling it as await b.a (which is stupid in hindsight, but one must try everything) doesn’t help.

I could do

b_a = (await db.scalars(sa.select(A).filter(A.id == b.a_id))).one()

but it’s too verbose for my taste (and gets really messy for complex relationships).

I found a lot of solutions for the other way around (one-to-many and many-to-many), but nothing for this use case.

Update to answer questions from comments:

I create the engine and the sessionmaker like this:

db_engine = create_async_engine(DB_URI, pool_recycle=3600, pool_pre_ping=True, echo_pool=True)
session_maker = sessionmaker(db_engine, AsyncSession, expire_on_commit=False, autocommit=False, autoflush=False)

And the way i query the object of B is:

query = sa.select(B).filter(B.id == requested_id)
result = (await db.execute(query)).one_or_none()  # type: ignore
b = result[0] if result else None
GergelyPolonkai
  • 6,230
  • 6
  • 35
  • 69

1 Answers1

0

modify your class B relation with this:

a = relationship(A,lazy='selectin')

and that should work properly