我试图找出一种以“正确的方式”使用SQLAlchemy范围的会话的正确方法,同时保持将会话的逻辑与配置分开并且与使用会话分开的逻辑。有人多次告诉我,一个好方法是拥有一些我可以在任何地方使用的全局scoped_session工厂:
"""myapp/db.py
"""
from sqlalchemy.orm import sessionmaker, scoped_session
Session = scoped_session(sessionmaker())
然后,当我想使用它时:
"""myapp/service/dosomething.py
"""
from myapp.db import Session
def do_something(data):
"""Do something with data
"""
session = Session()
bars = session.query(Bar).all()
for bar in bars:
bar.data = data
session.commit()
这似乎是正确的,但是我的问题是,在我所看到的所有示例中,它sessionmaker
还会设置会话的某些参数,即最重要的是绑定引擎。这对我来说毫无意义,因为实际的数据库引擎将在myapp.db
模块导入期间根据全局范围内未知的配置创建。
我所要做的是在应用程序的“ main”(或线程的main函数)中设置所有内容,然后仅假设该会话在其他位置进行了配置(例如,在do_something()
上述位置使用):
"""myapp/main.py
"""
from sqlalchemy import create_engine
from myapp.db import Session
from myapp.service.dosomething import do_something
def main():
config = load_config_from_file()
engine = create_engine(**config['db'])
Session.configure(bind=engine)
do_something(['foo', 'bar'])
这看起来像是正确的方法吗?我还没有找到这种流程的任何好例子,但我发现大多数其他例子似乎过于简化或特定于框架。
这是旧的,我从未接受过以下任何答案,但是在各种项目中,@ univerio的评论不断涌现,并且在SQLAlchemy中连续使用了3年以上,我现在选择的方法是继续按照我在OP中的建议进行操作:
myapp.db
定义以下内容的模块Session = ScopedSession(sessionmaker())
from myapp.db import Session
所需的任何地方main
或相关的初始化代码中,执行以下操作:def main():
config = load_config_from_file()
engine = create_engine(**config['db'])
Session.configure(bind=engine)
do_something(['foo', 'bar'])
我已经在Web应用程序,命令行工具和长期运行的后端流程中成功使用了这种模式,到目前为止,无需更改它。Ot很简单,可重用并且效果很好,我建议所有在这里绊脚的人都推荐它,因为他们问自己和我三年前一样。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句