SQLAlchemy:指定用于模型

时间:2015-05-26 13:57:13

标签: flask sqlalchemy flask-sqlalchemy

我正在使用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的代码和文档,但我找不到问题的根源或解决方案。

有什么方法可以指定在使用模型类创建对象时使用哪个会话?或者是否有一些完全不同的东西,我错过了会导致这个问题?

1 个答案:

答案 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()