我正在使用Flask-SQLAlchemy,我需要创建一个没有自动刷新操作的会话。但是,使用db.session
访问的Flask-SQLAlchemy创建的默认作用域会话已启用自动刷新。
我正在为100k行进行批量更新,并且自动刷新会导致严重的性能问题。
我尝试使用以下方法创建一个关闭自动刷新的新会话:
from flask_sqlalchemy import SignallingSession
db_session = SignallingSession(db, autoflush=False)
然后我尝试使用以下方法创建新行:
from flask_sqlalchemy import SQLAlchemy, BaseQuery
db = SQLAlchemy(app)
class Tool(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(1024), nullable=True)
add_tool = Tool()
add_tool.title = title
db_session.add(add_tool)
但是,这样做会引发以下异常:
Traceback (most recent call last):
File "app", line 182, in <module>
called for last item
import_tools('x.json', 1)
File "app", line 173, in import_tools
x.add_to_database()
File "app", line 126, in add_to_database
title=metadata['title'], commit=True)
File "app", line 150, in transfer
self.db_session.add(import_tool)
File ".virtualenvs/project/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 1492, in add
self._save_or_update_state(state)
File ".virtualenvs/project/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 1504, in _save_or_update_state
self._save_or_update_impl(state)
File ".virtualenvs/project/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 1759, in _save_or_update_impl
self._save_impl(state)
File ".virtualenvs/project/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 1731, in _save_impl
self._attach(state)
File ".virtualenvs/project/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 1849, in _attach
state.session_id, self.hash_key))
sqlalchemy.exc.InvalidRequestError: Object '<Tool at 0x11361f4d0>' is already attached to session '1' (this is '2')
我相信正在发生的事情是,在创建对象时,它会附加到Flask-SQLAlchemy提供的全局作用域会话,而我希望它附加到我创建的会话。我试着查看Flask-SQLAlchemy和SQLAlchemy的代码和文档,但我找不到问题的根源或解决方案。
有什么方法可以指定在使用模型类创建对象时使用哪个会话?或者是否有一些完全不同的东西,我错过了会导致这个问题?
答案 0 :(得分:5)
SQLAlchemy会话提供no_autoflush
context manager。这将暂停任何冲洗,直到您退出块。
model1 = Model(name='spam')
db.session.add(model1) # This will flush
with db.session.no_autoflush:
model2 = Model()
db.session.add(model2) # This will not
model2.name = 'eggs'
db.session.commit()