asynchronous - 异步 SQLalchemy:访问急切加载的空关系会触发新的延迟加载,引发错误
问题描述
我正在使用 sqlalchemy + asyncpg 和“选择”急切加载。
我有与 Friends 具有一对多关系的 Person 项目。
我在我的数据库中插入了一个 Person,没有相关的 Friend 条目。如果在同一个会话中我尝试从数据库中获取那个人,我可以很好地访问他们的静态(非关系)列,但不能访问friends
关系。
我认为尝试访问person.friends
会触发延迟加载,尽管它之前是作为selectin
加载强制执行的。为什么是这样?我怎样才能避免它?
# Create the ORM model
class Person(Base):
__tablename__ = 'items'
id_ = Column(POSTGRES_UUID(as_uuid=True), primary_key=True)
name = Column(String(32))
friends = relationship('Friend', lazy='selectin')
# Create an instance
person_id = uuid4()
person = Person(id_=person_id, name='Alice') # Note that this Person's friends are not set
# Add to database
async with AsyncSession(engine, expire_on_commit=False) as session:
try:
session.begin()
session.add(person)
await session.commit()
except:
await session.rollback()
raise
# Get the added person from the database
created_person = await session.get(person, person_id)
print(created_person.id_) # Works fine
print(created_person.friends) # Raises error
错误:
sqlalchemy.exc.MissingGreenlet: greenlet_spawn has not been called; can't call await_() here.
Was IO attempted in an unexpected place? (Background on this error at: https://sqlalche.me/e/14/xd2s)
解决方案
解决方案是使用以下populate_existing
参数get
:
populate_existing – 使方法无条件地发出 SQL 查询并用新加载的数据刷新对象,而不管对象是否已经存在。
代替
created_person = await session.get(person, person_id)
和
created_person = await session.get(person, person_id, populate_existing=True)
推荐阅读
- python - 无法使用 selenium 和 python 在 Google 页面上找到“类”
- oracle - 如何从函数参数中的列中获取所有值(创建时)?
- latex - LaTex 中的警告声明?
- php - 我想使用基于当前登录用户名的 php 脚本更新我的 MySQL 表
- service - QZ 在角度安装和 websocket 未找到错误
- c# - 使用限制器使用 MailKit 发送批量电子邮件失败,延迟 10 秒或更长时间
- python - 如何将 Python 程序的当前工作目录更改为用户的主目录?
- python - 如何输出嵌入在键中的键的值
- unit-testing - 测试自定义字段控件组件时如何提供NgControl?
- node.js - 如何通过 response.write 在 node.js 中正确发送缓冲区?