SQLAlchemy:指定用于模型的会话
SQLAlchemy: Specifying session to use for model
我正在使用 Flask-SQLAlchemy,我需要创建一个没有自动刷新操作的会话。但是,使用 db.session
访问的 Flask-SQLAlchemy 创建的默认作用域会话已打开自动刷新。
我正在对 10 万行进行批量更新,自动刷新导致了严重的性能问题。
我尝试使用以下方法创建一个关闭自动刷新的新会话:
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 的代码和文档,但找不到问题的根源或解决方案。
有什么方法可以指定在使用模型 class 创建对象时使用哪个会话?还是我遗漏了一些完全不同的东西会导致这个问题?
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()
我正在使用 Flask-SQLAlchemy,我需要创建一个没有自动刷新操作的会话。但是,使用 db.session
访问的 Flask-SQLAlchemy 创建的默认作用域会话已打开自动刷新。
我正在对 10 万行进行批量更新,自动刷新导致了严重的性能问题。
我尝试使用以下方法创建一个关闭自动刷新的新会话:
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 的代码和文档,但找不到问题的根源或解决方案。
有什么方法可以指定在使用模型 class 创建对象时使用哪个会话?还是我遗漏了一些完全不同的东西会导致这个问题?
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()