Reputation: 543
I am using Flask-SQLAlchemy and I need to create a session without auto-flushing for an operation. However, the default scoped session that is created by Flask-SQLAlchemy which is accessed using db.session
has auto-flushing turned on.
I'm doing bulk updates for 100k rows, and the auto-flushing is causing severe performance issues.
I tried creating a new session with auto-flushing turned off using:
from flask_sqlalchemy import SignallingSession
db_session = SignallingSession(db, autoflush=False)
And then I tried creating a new row using:
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)
However, doing this throws the following exception:
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')
What I believe is happening is that when the object is created, it is attached to the global scoped session that is provided by Flask-SQLAlchemy, while I want it to be attached to the session that I created. I tried looking through the code and documentation for Flask-SQLAlchemy and SQLAlchemy, but I couldn't find either the source of the problem or the solution to it.
Is there some way I can specify which session to use when the object is created using the model class? Or is there something totally different that I am missing which would be causing this problem?
Upvotes: 3
Views: 2455
Reputation: 20709
SQLAlchemy sessions provide a no_autoflush
context manager. This will suspend any flushes until after you exit the block.
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()
Upvotes: 6