sqlalchemy Session 对象没有添加属性

zai*_*d98 3 python sqlalchemy fastapi

我正在尝试将数据插入 mysql 服务器,当我尝试将数据添加到 SQLalchemy 会话时,我收到错误“生成器对象没有添加属性”

db=get_db()
temp = schema.User(**filtered_dict)
insert_data=models.User(**temp.dict())
db = get_db()
db.add(insert_data)
db.commit()
db.refresh()
Run Code Online (Sandbox Code Playgroud)

会话生成器:

def get_db():
 
    db_session = sessionlocal()
    try:
        yield db_session
    finally:
        db_session.close()
Run Code Online (Sandbox Code Playgroud)

会话创建


from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

SQLALCHEMY_DATABASE_URL = "mysql+mysqlconnector://root:password@localhost:3305/line_api"

engine = create_engine(
    SQLALCHEMY_DATABASE_URL
)
sessionlocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)


Base = declarative_base()
Run Code Online (Sandbox Code Playgroud)

请帮忙...

TFl*_*oom 6

简单的解决方案

我在自己的 SQLAlchemy FastAPI 项目中遇到了类似的问题。该问题源于从关键字收集数据库会话yieldyield返回一个生成器,而不是像您期望的那样返回 sqlalchemy 数据库会话。您可以在此处阅读有关收益表达式的更多信息: https://docs.python.org/3/reference/expressions.html#yieldexpr

要修复代码,您需要__next__以某种形式对generator从返回的对象调用内部函数get_db。您可以通过多种方式来完成此操作(有些方式可能比我的建议在风格上更准确)。

temp = schema.User(**filtered_dict)
insert_data=models.User(**temp.dict())
db_gen = get_db()
db = next(db_gen)
db.add(insert_data)
db.commit()
db.refresh()
Run Code Online (Sandbox Code Playgroud)

使用 var 引用编辑生成器感谢评论中的@DustinMichels。

添加next函数调用应该可以解决问题。


使用异步生成器

由于我们没有在函数前面加上 ,所以get_db我们async得到了一个普通的生成器。然而,如果我们添加async这个函数定义,我们就不能再用作__next__解决方案了。使函数异步还有助于确保正确关闭连接(请参阅注释)。

如果开发人员决定添加关键字,async那么您有几个选择:

FastAPI 的Depends系统确实可以与异步生成器完美配合,并且可以为您调用该函数,并使用您的连接填充一个不错的参数。

或者,您可以调用asend(None)异步生成器来获取异步生成器的第一个值。(还有更好的方法可以做到这一点,例如使用异步 for 循环或__anext__函数调用)。更多内容请阅读:https ://www.python.org/dev/peps/pep-0525/#implementation-details

async def get_db():
    db_session = sessionlocal()
    try:
        yield db_session
    finally:
        db_session.close()

# ...

temp = schema.User(**filtered_dict)
insert_data=models.User(**temp.dict())
db = get_db().asend(None)
db.add(insert_data)
db.commit()
db.refresh()
Run Code Online (Sandbox Code Playgroud)