我试图找出正确的方法来使用SQLAlchemy作用域会话"正确的方法"同时保持定义会话的逻辑与配置分开并与使用会话分开。有人告诉我,有一个很好的方法是建立一个全球范围的工厂,我可以随处使用:
"""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"中设置所有内容。 (或在线程的主要功能中),然后假设会话在其他地方配置(例如上面的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'])
这看起来是正确的做法吗?我没有找到任何这种流程的好例子,但我发现的大多数其他例子似乎都过于简化或特定于框架。
答案 0 :(得分:1)
这很老了,我从未接受过以下任何答案,但由于@univerio的评论以及在SQLAlchemy中多个项目中连续使用了3年以上,我现在选择的方法是继续完全按照我在操作:
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非常简单,可重用并且效果很好,我建议所有在这里绊脚的人都推荐它,因为他们问自己和我三年前一样。
答案 1 :(得分:0)
您可以做的是将配置分成一个单独的模块:
"""myapp/cfg.py
"""
config = load_config_from_file()
然后您可以在任何需要的地方导入此文件,包括在db
模块中,这样您就可以构建引擎以及会话:
"""myapp/db.py
"""
from .cfg import config
engine = create_engine(**config['db'])
Session = scoped_session(sessionmaker(bind=engine))
答案 2 :(得分:0)
想想单身人士。
在您的情况from myapp.db import Session
中,Session是单例和全局的。
只需在应用程序的开头配置Session即可。
您应该有一个配置过程,例如从文件或env加载配置数据,在所有配置准备就绪后,运行真实程序。