2009-08-22 12 views
64

私はこのような何かやりたい:sqlalchemy flush()および挿入されたIDを取得しますか?

f = Foo(bar='x') 
session.add(f) 
session.flush() 

# do additional queries using f.id before commit() 
print f.id # should be not None 

session.commit() 

をしかし、私はそれをしようとすると、いずれもf.idではありません。これをどのように機能させることができますか?

-Dan

+2

'echo = True'を使用してSAエンジンを初期化し、フラッシュ時に実行されるSQLを確認できますか?あなたが何を記述するか*は*働いてIDを与えるべきですが、f.idがNoneであるという別の問題があるかもしれません。 –

答えて

37

サンプルコードはそのまま動作するはずです。 Sqlalchemyは、自動生成する主キー列を前提にして、f.idの値を指定する必要があります。主キー属性はflush()プロセス内で生成されるとすぐに取り込まれ、commit()の呼び出しは必要ありません。したがって、ここでの答えは、あなたのマッピングの詳細です。使用中のバックエンドの奇妙な癖がある場合(SQLiteはコンポジット主キーの整数値を生成しません)、および/または発行されたSQLがエコーをオンにします。

+0

正しいですが、シェルのクイックチェックでは、プライマリキーフィールドに値が設定されていることがわかります。なぜそれが実際に働いていないのかを調べなければならないでしょう。 – Eloff

+2

"あなたのサンプルコードは値を提供するはずです"というのは、 "あたかもそのコードがそのまま動作していたはず"ではなく、 "最初にidの値を与えておくべきだった"というように聞こえる。 3回目の読書の後で初めて、後者よりも後者を意味することが私にはっきりと分かりました。明確にできますか? – stochastic

-7

あなたはsession.save_or_update(f)代わりのsession.add(f)を使用してみてください。

+1

'save_or_update'は0.5前後で廃止されました。 'session.add()'はそれを行うべきです。 –

93

私はちょうど同じ問題を抱えてテストした後、私はこれらの答えのどれもが十分ではないことを発見しました。

session.refresh)(:

現在、またはSQLAlchemyの.6+のように、非常に簡単な解決策は、(これは以前のバージョンに存在している場合、私はそれがない想像しても、私は、知っていない)があります

f = Foo(bar=x) 
session.add(f) 
session.flush() 
# At this point, the object f has been pushed to the DB, 
# and has been automatically assigned a unique primary key id 

f.id 
# is None 

session.refresh(f) 
# refresh updates given object in the session with its state in the DB 
# (and can also only refresh certain attributes - search for documentation) 

f.id 
# is the automatically assigned primary key ID given in the database. 

それを行う方法は次のとおりです。

だから、あなたのコードは次のようになります。

+6

これは私にとってはうまくいくかもしれない答えに近づいていますが、次のエラーが表示されます。InvalidRequestError:インスタンス '<....>'を更新できませんでした。フラッシュ後、インスタンスは単に存在しなくなります。任意の洞察力を賞賛してください。 – PlaidFan

+1

あなたはちょうど私のお尻を保存しました。私はDjangoから来るORMを再び使用するとは思わない。 flush()コマンドは、IMHOとして文書化されているようには機能しません。 –

+1

アップデートでは、 '' sessionmaker(autoflush = True) '' 'を使用しなければならなかったので、refresh()と組み合わせると行IDが与えられました。 #grrr –

4

dpbの回答とは異なり、リフレッシュは必要ありません。 一度フラッシュするとidフィールドにアクセスできます。sqlalchemyはバックエンドで自動生成されたIDを自動的に更新します

この問題が発生しました。私のフォームでは、idはhiddenfieldで表現されていました(私は私のフォームにidを表示したくないので)。非表示のフィールドは、デフォルトでテキストとして表されます。一度フォームをwidget = hiddenInput()で整数フィールドに変更すると問題は解決しました。

+1

refresh()データの移行では、ループ内で行IDを必要とし、FKを移入する必要がありました。コミット、フラッシュ、セッションのハッキング、リフレッシュのすべてのコンボを試しました。私のデータはきれいで清潔で、SQLAが本当にうまくいきません(少なくとも5つの主要なORMSにかなりの効果があります)。 add() - > commit()/ flush()の行IDを取得しようとすると、5時間以上をラッピングするだけです。 –

1

私はかつてメソッドを呼び出す前にidに0を割り当てたことで問題がありました。 IDはデータベースによって正しく割り当てられましたが、session.flush()の後に正しいIDがセッションから取得されませんでした。

関連する問題