Reputation: 2890
I've seen a lot of problems with SessionMaker, but this one is slightly different. Not sure why, but sqlalchemy won't let my session object commit.
In my app, I have some code that does:
views.py
rec = session.query(Records).filter(Records.id==r).first()
n = rec.checkoutRecord(current_user.id)
session.add(n)
session.commit()
models.py:
class Records(UserMixin, CRUDMixin, Base):
__table__ = Table('main_records', Base.metadata, autoload=True)
def checkoutRecord(self,uid):
self.editing_uid = uid
self.date_out = datetime.now()
return self
def checkinRecord(self,uid):
self.editing_uid = uid
self.date_in = datetime.now()
return self
The program craps out on the commit(), giving the above exception. Interestingly, some test code which does not import flask, but does import sqlalchemy works fine and lets me commit without error.
The full stack-trace:
Traceback (most recent call last):
File "/Users/bhoward/Envs/py27/lib/python2.7/site-packages/flask/app.py", line 1475, in full_dispatch_request
rv = self.dispatch_request()
File "/Users/bhoward/Envs/py27/lib/python2.7/site-packages/flask/app.py", line 1461, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/Users/bhoward/Envs/py27/lib/python2.7/site-packages/flask_login.py", line 663, in decorated_view
return func(*args, **kwargs)
File "/Users/bhoward/projects/PeerCoUI/mk2/peercoui/app/records/views.py", line 65, in select_view
session.commit()
File "/Users/bhoward/Envs/py27/lib/python2.7/site-packages/sqlalchemy/orm/scoping.py", line 149, in do
return getattr(self.registry(), name)(*args, **kwargs)
File "/Users/bhoward/Envs/py27/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 721, in commit
self.transaction.commit()
File "/Users/bhoward/Envs/py27/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 354, in commit
self._prepare_impl()
File "/Users/bhoward/Envs/py27/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 323, in _prepare_impl
self.session.dispatch.before_commit(self.session)
File "/Users/bhoward/Envs/py27/lib/python2.7/site-packages/sqlalchemy/event.py", line 372, in __call__
fn(*args, **kw)
File "/Users/bhoward/Envs/py27/lib/python2.7/site-packages/flask_sqlalchemy/__init__.py", line 162, in session_signal_before_commit
d = session._model_changes
AttributeError: 'Session' object has no attribute '_model_changes'
Full code for the project is in github: https://github.com/bhoward00/peercoui
Any advice appreciated
Upvotes: 23
Views: 42441
Reputation: 41
I solved this problem do exchange session.exec
to session.execute
.
I not did deep analysis about this. I think this is due to the fact that SessionMaker
returned object, that not original Session
Upvotes: -1
Reputation: 11
The SQLAlchemy==1.4.x version is not working for me.
Change to SQLAlchemy==1.3.18 though, and it worked.
How to create such a file to specify the installed versions?
Edit the requirements.txt and the SQLAlchemy entry to Eg SQLAlchemy==1.3.18.
Then, re-run your virtual env. --> flask run
If you have not set a virtual env?
Hope that helps !
Upvotes: 0
Reputation: 381
I had the same problem as well and solved it by modifying the _SessionSignalEvents
class within __init__.py
in flask-sqlalchemy
. However, I just noticed that such a fix had already been in place since 8 months on the official repository.
If you encounter a similar problem, I would recommend you to pull the latest version of the project from github (https://github.com/mitsuhiko/flask-sqlalchemy/) since the one currently available through pip install is outdated.
Upvotes: 2
Reputation: 2665
Yes this is exactly problem when using flask-sqlalchemy
models mixed with pure sqlalchemy
session. Thing is that flask-sqlalchemy
subclasses the base Session
from sqlalchemy
and adds some internals one of which is the _model_changes
dict. This dict is used for model modification tracking.
So if you want to use flask-sqlalchemy
based models with regular sqlalchemy
session, one way would be to just add the dict to the session (this is just example code):
def create_session(config):
engine = create_engine(config['DATABASE_URI'])
Session = sessionmaker(bind=engine)
session = Session()
session._model_changes = {}
return session
I had the same exact problem as you, so hopefully this should help you.
UPDATE:
There is new version available, which should be fixing this behaviour, quoting the 2.0 docs:
Changed how the builtin signals are subscribed to skip non Flask-SQLAlchemy sessions. This will also fix the attribute error about model changes not existing.
Docs: http://flask-sqlalchemy.pocoo.org/2.0/changelog/#version-2-0
Upvotes: 29