我试图找出以“正确的方式”使用 SQLAlchemy 范围会话的正确方法,同时将定义会话的逻辑与配置分开并与使用会话分开。我多次被告知,一个好的方法是拥有一些全局 scoped_session 工厂,我可以在任何地方使用:
"""myapp/db.py
"""
from sqlalchemy.orm import sessionmaker, scoped_session
Session = scoped_session(sessionmaker())
Run Code Online (Sandbox Code Playgroud)
然后当我想使用它时:
"""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()
Run Code Online (Sandbox Code Playgroud)
这似乎是正确的,但我的问题是在我看到的所有示例中,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'])
Run Code Online (Sandbox Code Playgroud)
这看起来是正确的方法吗?我还没有找到这种流程的任何好的例子,但我发现的大多数其他例子似乎过于简化或特定于框架。
she*_*ron 11
这是旧的,我从来没有接受下面的任何答案,但是在各种项目中传递@univerio 的评论和 3+ 年在 SQLAlchemy 中的持续使用,我现在选择的方法是继续完全按照我在 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'])
Run Code Online (Sandbox Code Playgroud)
我已经在 Web 应用程序、命令行工具和长时间运行的后端进程中成功地使用了这种模式,并且迄今为止从未改变过它。Ot 很简单、可重复使用且效果很好,我会向在这里磕磕绊绊的任何人推荐它,因为他们问过自己和我 3 年前做过的一样的问题。
| 归档时间: |
|
| 查看次数: |
7805 次 |
| 最近记录: |