我有目的地定义了2个不同的引擎(使用相同的DB URL),用于2个具有不同配置的会话,Pyramid的model.py
:
DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
DBSessionTask = scoped_session(sessionmaker(extension=ZopeTransactionExtension(), expire_on_commit=False))
配置会话(在Pyramid应用程序的主__init__.py
中):
engine = engine_from_config(settings, 'sqlalchemy.')
DBSession.configure(bind=engine)
Base.metadata.bind = engine
engine_task = engine_from_config(settings, 'sqlalchemy.')
DBSessionTask.configure(bind=engine_task)
会话旨在用于2个不同类别的对象(DBSessionTask
用于在应用程序范围设置中保存的长期监督对象,DBSession
用于“数据”对象上的典型范围会话一个网络应用程序)。
我收到了警告:
sqlalchemy\orm\scoping.py:99: SAWarning: At least one scoped session is already present. configure() can not affect sessions that have already been created.
warn('At least one scoped session is already present. '
这是两个不同的引擎,为什么SQA会警告我呢?他们当然使用相同的DB url,但为什么这应该是一个问题?
答案 0 :(得分:1)
如果要在Pyramid + SQLAlchemy中使用多个会话,则应明确管理它们,而不是依赖范围会话。范围会话sessionmaker期望每个线程创建一个会话,因此您的问题。许多金字塔开发者更喜欢这样做作为一般规则,因为它非常适合通过请求和上下文对象传递所有内容的金字塔哲学。我的首选是创建一个db引擎组件,它具有获取和关闭会话的方法,并通过配置器注册该组件。然后我有一个自定义请求工厂,它在请求开始时创建数据库会话,并在最后提交或回滚它。通过在配置程序部分注册请求生命周期回调,您也可以在没有自定义请求工厂的情况下执行相同的操作。以下是从烹饪书中获取上述内容的示例,您可以轻松地适应多个引擎:
http://pyramid-cookbook.readthedocs.org/en/latest/database/sqlalchemy.html
# __init__.py
from pyramid.config import Configurator
from sqlalchemy import engine_from_config
from sqlalchemy.orm import sessionmaker
def db(request):
maker = request.registry.dbmaker
session = maker()
def cleanup(request):
if request.exception is not None:
session.rollback()
else:
session.commit()
session.close()
request.add_finished_callback(cleanup)
return session
def main(global_config, **settings):
config = Configurator(settings=settings)
engine = engine_from_config(settings, prefix='sqlalchemy.')
config.registry.dbmaker = sessionmaker(bind=engine)
config.add_request_method(db, reify=True)
答案 1 :(得分:0)
您应该使用一个范围会话将模型绑定到不同的数据库引擎。