簡體   English   中英

greenlet_spawn 尚未被調用

[英]greenlet_spawn has not been called

我正在嘗試獲取一對多關系中匹配的行數。 當我嘗試parent.children_count我得到:

sqlalchemy.exc.MissingGreenlet:尚未調用 greenlet_spawn; 不能在這里調用 await_only() 。 是否在意想不到的地方嘗試了 IO? (此錯誤的背景信息: https ://sqlalche.me/e/14/xd2s)

我添加了expire_on_commit=False但仍然出現相同的錯誤。 我怎樣才能解決這個問題?

import asyncio
from uuid import UUID, uuid4
from sqlmodel import SQLModel, Relationship, Field
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession

class Parent(SQLModel, table=True):
    id: UUID = Field(default_factory=uuid4, primary_key=True)
    children: list["Child"] = Relationship(back_populates="parent")
    @property
    def children_count(self):
        return len(self.children)

class Child(SQLModel, table=True):
    id: UUID = Field(default_factory=uuid4, primary_key=True)
    parent_id: UUID = Field(default=None, foreign_key=Parent.id)
    parent: "Parent" = Relationship(back_populates="children")

async def main():
    engine = create_async_engine("sqlite+aiosqlite://")
    async with engine.begin() as conn:
        await conn.run_sync(SQLModel.metadata.create_all)

    async with AsyncSession(engine) as session:
        parent = Parent()
        session.add(parent)
        await session.commit()
        await session.refresh(parent)
        print(parent.children_count)  # I need 0 here, as of now this parent has no children

asyncio.run(main())

我認為這里的問題是默認情況下 SQLAlchemy 延遲加載關系,因此訪問parent.children_count隱式觸發導致報告錯誤的數據庫查詢。

解決這個問題的一種方法是在關系定義中指定一個不同於“惰性”的加載策略 使用 SQLModel,這看起來像:

children: list['Child'] = Relationship(
    back_populates='parent', sa_relationship_kwargs={'lazy': 'selectin'}
)

這將導致 SQLAlchemy 在仍處於“異步模式”時發出額外的查詢來獲取關系。 另一種選擇是傳遞{'lazy': 'joined'} ,這將導致 SQLAlchemy 在單個JOIN查詢中獲取所有結果。

如果不需要配置關系,您可以發出指定選項的查詢:

from sqlalchemy.orm import selectinload
from sqlmodel import select

    ...
    async with AsyncSession(engine) as session:
        parent = Parent()
        session.add(parent)
        await session.commit()
        result = await session.scalars(
            select(Parent).options(selectinload(Parent.children))
        )
        parent = result.first()
        print(
            parent.children_count
        )  # I need 0 here, as of now this parent has no children

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM