2012-12-14 19 views
17

私はSQLAlchemyを使い慣れておらず、オリジナルの著者にアクセスできないやや乱雑なコードベースを継承しています。いつSQLAlchemyでflush()を呼び出す必要がありますか?

コードは、DBSession.flush()へのコールでリラックスされています。作者がデータが保存されていることを確認したいときはいつでもそうです。最初は私がこのコードで見たパターンにちょうど従っていましたが、私はドキュメントを読んでいるので、これは不要であると思われます。さらに、「InvalidRequestError:セッションが既にフラッシングしています」というエラーを生成するAJAX呼び出しでは、いくつかのケースに遭遇しました。

どのようなシナリオで、私は合法的にflush()を呼びたいと思っていましたか?

これは、ピラミッドのアプリで、SQLAlchemyのはで設定されている:pyramid_tmはあなたのためのすべてのコミットを処理するプロジェクトに積極的であることを

一緒に DBSession
DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension(), expire_on_commit=False)) 
Base = declarative_base() 

答えて

26

ZopeTransactionExtension

  • 新しいオブジェクトを作成して元のキーに戻したい場合は、次のようにします。

    DBSession.add(obj) 
    DBSession.flush() 
    log.info('look, my new object got primary key %d', obj.id) 
    
  • あなたはそれがトランザクション全体を無効にすることなく、失敗した場合、セーブポイントとロールバックでいくつかのSQLを実行しようとします。 ORMを含む他のすべての場合には

    sp = transaction.savepoint() 
    try: 
        foo = Foo() 
        foo.id = 5 
        DBSession.add(foo) 
        DBSession.flush() 
    except IntegrityError: 
        log.error('something already has id 5!!') 
        sp.rollback() 
    

、トランザクションは、例外時に、あなたのために中止され、またはpyramid_tmによって自動的に成功するとコミットされます。未処理のSQLを実行する場合はtransaction.commit()を実行するか、セッションをダーティーとしてzope.sqlalchemy.mark_changed(DBSession)でマークする必要があります。そうしないと、セッションが変更されたことをZTEが認識できなくなります。

また、expire_on_commitはデフォルトでTrueのままにしておきます

+0

ありがとうございます。フォローアップ:この設定でexpire_on_commit = Falseを設定する本当に良い理由は何ですか? (私はなぜそれが最初の場所でこのように設定されたのかわかりません)。 – blocks

+4

私の経験上、彼らは何をしているのか分からず、コミット後にオブジェクトを使ってシステムを不正行為しようとする人たちによって使用されています。 *明らかにコミット後、そのオブジェクトの状態がもう有効であるという保証はありません。 –

+0

@Michael Merickel - 非常によく説明されています。では、flush()を使用しないでください。 [コード内にSQLAlchemy flush()を呼び出すことによる副作用はありますか?](http://stackoverflow.com/questions/29338419/are-there-any-side-effects-from-calling-sqlalchemy-flush-within-code ) –

関連する問題