私はこのようなことをしたい:
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
がNone
それを試すときです。どうすればこれを機能させることができますか?
私はこのようなことをしたい:
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
がNone
それを試すときです。どうすればこれを機能させることができますか?
同じ問題に遭遇したばかりですが、テストした結果、これらの答えのどれも十分ではないことがわかりました。
現在、またはsqlalchemy .6 +の時点で、非常に単純な解決策があります(これが以前のバージョンに存在するかどうかはわかりませんが、存在すると思います)。
session.refresh()
したがって、コードは次のようになります。
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.
それがその方法です。
サンプルコードはそのまま機能するはずです。SQLAlchemyはf.id
、自動生成される主キー列を想定して、の値を提供する必要があります。主キー属性は、生成されるとすぐにflush()
プロセス内に入力されるため、を呼び出すcommit()
必要はありません。したがって、ここでの答えは、次の1つ以上にあります。
みなさん、ありがとうございました。列マッピングを変更することで問題を解決しました。私にとっては、autoincrement=True
が必要です。
元:
id = Column('ID', Integer, primary_key=True, nullable=False)
変更後:
id = Column('ID', Integer, primary_key=True, autoincrement=True, nullable=True)
それから
session.flush()
print(f.id)
大丈夫です!
dpbによる回答とは異なり、更新は必要ありません。フラッシュすると、idフィールドにアクセスでき、sqlalchemyはバックエンドで自動生成されたIDを自動的に更新します
この問題に遭遇し、調査の結果、正確な理由を突き止めました。モデルはidをintegerfieldとして作成し、フォームではidをhiddenfieldで表しています(フォームにidを表示したくなかったため)。非表示フィールドは、デフォルトではテキストとして表されます。widget = hiddenInput()でフォームをintegerfieldに変更すると、問題は解決しました。
0
メソッドを呼び出す前にidに割り当てる際に問題が発生したことがありsession.add
ます。IDはデータベースによって正しく割り当てられましたが、後のセッションから正しいIDが取得されませんでしたsession.flush()
。
コアソリューションは他のはるかに古い回答で言及されていますが、これは新しい非同期APIを使用します。
sqlalchemy == 1.4(2.0スタイル)では、以下が機能するようです:
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.ext.asyncio import create_async_engine
engine = create_async_engine(
"postgresql+asyncpg://user:pass@localhost/db",
echo=False,
)
# expire_on_commit=False will prevent attributes from being expired
# after commit.
async_session = sessionmaker(
engine, expire_on_commit=False, class_=AsyncSession,
)
# default kwarg autoflush=True
async with async_session() as session:
async with session.begin():
f = Foo(bar='x')
session.add(f)
print(f.id)
# None
await session.flush()
print(f.id)
# not None
# commits transaction, closes session
私のコードは次のように機能します。
f = Foo(bar="blabla")
session.add(f)
session.flush()
session.refresh(f, attribute_names=[columns name that you want retrieve]
# so now you can access the id inserted, for example
return f.id # id inserted will be returned
session.save_or_update(f)
の代わりにを使用してみてくださいsession.add(f)
。