如何在SQLAlchemy插入数据后返回Base类对象?
解决SQLAlchemy异步插入后返回对应模型对象的问题
正确实现方式(异步场景)
你用的是SQLAlchemy 1.4异步模式+asyncpg,要插入后返回完整的EdaToken对象,推荐用ORM标准流程:session.add() + commit() + refresh(),确保拿到数据库自动生成的字段(比如自增id)。
示例代码:
from sqlalchemy.ext.asyncio import AsyncSession from your_module import EdaToken async def create_eda_token(db: AsyncSession, token_data: dict) -> EdaToken: # 每次插入都创建新的模型实例 new_token = EdaToken(**token_data) db.add(new_token) await db.commit() # 刷新对象,同步数据库端生成的字段值 await db.refresh(new_token) return new_token
两种错误写法的问题分析
第一种:报错'CursorResult' object has no attribute 'id'
这种情况是直接用了SQLAlchemy Core层的execute()插入,没有转换为ORM对象。比如错误代码类似:
result = await db.execute(insert(EdaToken).values(**token_data)) return result.id # CursorResult是Core执行结果,不是EdaToken实例
如果坚持用Core方式,需要结合returning()子句获取完整对象:
result = await db.execute(insert(EdaToken).values(**token_data).returning(EdaToken)) new_token = result.scalar_one() return new_token
但还是更推荐ORM的add()+refresh()写法,更贴合ORM设计逻辑。
第二种:仅能插入一次,后续返回旧对象
核心问题是重复复用了同一个模型实例。比如错误代码把实例定义在函数外部:
# 错误示例:全局实例导致重复插入失效 new_token = EdaToken() async def create_eda_token(db: AsyncSession, token_data: dict): new_token.__dict__.update(token_data) db.add(new_token) await db.commit() return new_token
第一次插入后,该实例已被会话标记为持久化状态,后续修改再添加会被SQLAlchemy判定为更新操作,不会生成新记录,自然返回旧对象。解决办法就是每次插入都在函数内部创建新的EdaToken实例。
额外注意点
- 确保
EdaToken的主键字段(比如id)配置了自增:
from sqlalchemy import Column, Integer from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class EdaToken(Base): __tablename__ = 'eda_token' id = Column(Integer, primary_key=True, autoincrement=True) # 其他业务字段...
- 异步操作必须全程用
await执行数据库方法(commit、refresh、execute等),不能遗漏异步关键字。
内容的提问来源于stack exchange,提问作者Plaoo
相关产品推荐
相关产品推荐

