Python 为什么用sqlalchemy打开同一个数据库,但得到不同的结果,我如何更新它?

Python 为什么用sqlalchemy打开同一个数据库,但得到不同的结果,我如何更新它?,python,sqlalchemy,Python,Sqlalchemy,我用pytest编写了一些测试,我想用post方法测试创建用户和电子邮件。 通过一些调试,我知道问题在于我在内存中打开了两个数据库,但它们是相同的数据库SessionLocal()。 因此,如何解决这个问题,我尝试了db.flush(),但它不起作用 这是post方法代码 @router.post(“/”,response\u model=schemas.User) def创建用户( *, db:Session=dependens(deps.get_db),#get_db是SessionLoca

我用pytest编写了一些测试,我想用post方法测试创建用户和电子邮件。 通过一些调试,我知道问题在于我在内存中打开了两个数据库,但它们是相同的数据库
SessionLocal()
。 因此,如何解决这个问题,我尝试了
db.flush()
,但它不起作用

这是post方法代码

@router.post(“/”,response\u model=schemas.User)
def创建用户(
*,
db:Session=dependens(deps.get_db),#get_db是SessionLocal()
schemas.UserCreate中的用户\u,
当前用户:models.user=依赖(deps.get\u current\u active\u superuser),
)->任何:
"""
创建新用户。
"""
user=crud.user.get_by_email(db,email=user_in.email)
如果用户:
引发HTTPException(
状态代码=400,
detail=“系统中已存在具有此用户名的用户。”,
)
user=crud.user.create(db,obj\u in=user\u in)
打印(“==post==”)
打印(db.query(models.User.count())
打印(db)
如果已启用settings.EMAILS_并在.email中使用用户_:
发送新帐户电子邮件(
email\u to=user\u in.email,username=user\u in.email,password=user\u in.password
)
返回用户
测试代码为:

def test\u create\u user\u new\u email(
client:TestClient,superuser_token_headers:dict,db:Session#db是SessionLocal()
)->无:
用户名=随机电子邮件()
密码=随机\u下\u字符串()
数据={“电子邮件”:用户名,“密码”:密码}
r=client.post(
f“{settings.API_V1_STR}/users/”,headers=superuser\u token\u headers,json=data,
)
断言200断言用户
E断言没有
==职位====
320
==测试====
319

您的代码没有提供足够的信息来帮助您,关键问题可能在于您的注释所隐藏和解释的内容

您似乎混淆了sqlalchemy会话和数据库。如果您不熟悉这些概念,我强烈建议您看看

但是,看看您的代码结构,您似乎正在使用FastAPI

然后,如果您想使用pytest测试SQLAlchemy,我建议您将pytest fixture用于SQL事务

以下是我对如何实施这种测试的建议。我假设您希望在实际数据库上运行测试,而不是特别为测试创建新数据库。这个实现很大程度上基于(作者提出了一个“放心使用语句”,所以我想他同意我在这里复制他的代码):

#test.py
导入pytest
从sqlalchemy导入创建引擎
从sqlalchemy.orm导入会话
从fastapi.testclient导入testclient
从myapp.models导入BaseModel
从myapp.main导入应用程序#导入您的fastapi应用程序
从myapp.database import get_db#导入依赖项
client=TestClient(应用程序)
#scope=“session”表示发动机将持续整个测试会话
@pytest.fixture(scope=“session”)
def引擎():
返回创建引擎(“postgresql://localhost/test_database")
#在测试会话结束时,使用fixture和yield删除创建的元数据
@pytest.fixture(scope=“session”)
def表(发动机):
BaseModel.metadata.create_all(引擎)
产量
BaseModel.metadata.drop_all(引擎)
#这里scope=“function”(默认情况下),因此每次测试完成时,都会清理数据库
@pytest.fixture
def dbsession(引擎、表格):
“”“返回sqlalchemy会话,测试后正确地删除所有内容。”“”
连接=引擎。连接()
#开始嵌套事务
事务=连接。开始()
#使用已启动事务的连接
会话=会话(绑定=连接)
收益期
session.close()
#回滚更广泛的事务
事务。回滚()
#将连接放回连接池
连接。关闭()
##gist.github代码的结尾
@pytest.fixture
def db_fastapi(dbsession):
def override_get_db():
db=dbsession
尝试:
收益率分贝
最后:
db.close()
client.app.dependency\u overrides[get\u db]=override\u get\u db
收益率分贝
#现在您可以运行测试了
def测试\创建\用户\新\电子邮件(db\ U fastapi):
用户名=随机电子邮件()
# ...

deps.get_db
def get_db()->生成器:try:db=SessionLocal()最终生成db:db.close()
,而
db:Session
@pytest.fixture(scope=“Session”)def db()->生成器:yield SessionLocal()
。关于
SessionLocal()
engine=create\u engine(settings.SQLALCHEMY\u DATABASE\u URI,pool\u pre\u ping=True)SessionLocal=sessionmaker(autocommit=False,autoflush=False,bind=engine)
,我对这种评论格式感到抱歉。你可以用这些片段编辑你的问题。但在这里,我们可以理解为什么它们不是同一个对象。每次调用
SessionLocal
,您都会创建一个新实例。谢谢,我用创建一个实例来修复它。
>       assert user
E       assert None

====post====
320
<sqlalchemy.orm.session.Session object at 0x7f0a9f660910>
====test====
319
<sqlalchemy.orm.session.Session object at 0x7f0aa09c4d60>