web-dev-qa-db-ja.com

sqlalchemyフラスコ:AttributeError: 'Session'オブジェクトにはsession.commit()の属性 '_model_changes'がありません

SessionMakerで多くの問題を見てきましたが、これは少し異なります。理由は不明ですが、sqlalchemyではセッションオブジェクトをコミットできません。

私のアプリには、次のようなコードがあります。

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

プログラムはcommit()をクラップアウトして、上記の例外を出します。興味深いことに、フラスコをインポートしないがsqlalchemyをインポートするいくつかのテストコードは正常に動作し、エラーなしでコミットできます。

完全なスタックトレース:

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'

プロジェクトの完全なコードはgithubにあります: https://github.com/bhoward00/peercoui

助言をいただければ幸いです

17
bhoward

はい、これは、純粋なsqlalchemyセッションと混合されたflask-sqlalchemyモデルを使用する場合、まさに問題です。ことは、flask-sqlalchemySessionからベースsqlalchemyをサブクラス化し、その内部の1つが_model_changes dictである内部を追加することです。この辞書は、モデル変更の追跡に使用されます。

したがって、通常のsqlalchemyセッションでflask-sqlalchemyベースのモデルを使用する場合、1つの方法はセッションにdictを追加することです(これはサンプルコードです):

def create_session(config):
    engine = create_engine(config['DATABASE_URI'])
    Session = sessionmaker(bind=engine)
    session = Session()
    session._model_changes = {}
    return session 

私はあなたと同じ正確な問題を抱えていたので、うまくいけばこれがあなたを助けるでしょう。

UPDATE:

2.0のドキュメントを引用して、この動作を修正する新しいバージョンが利用可能です。

組み込みシグナルがサブスクライブされる方法を変更して、Flask-SQLAlchemy以外のセッションをスキップします。これにより、存在しないモデル変更に関する属性エラーも修正されます。

ドキュメント: http://flask-sqlalchemy.pocoo.org/2.0/changelog/#version-2-

24
jbub

私も同じ問題を抱えており、フラスコのsqlalchemyのinit。py内の_SessionSignalEventsクラスを変更することで解決しました。ただし、そのような修正が公式リポジトリで8か月以来すでに行われていることに気づきました。

同様の問題が発生した場合は、プロジェクトの最新バージョンをgithub( https://github.com/mitsuhiko/flask-sqlalchemy/ )から削除することをお勧めします。 pipインストールが古くなっています。

2
olipo186