2009-08-22 89 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在flush-time被執行?你所描述的*應該*工作,並給你的身份證,但可能會有一些其他問題導致f.id爲無。 – 2009-08-23 00:07:20

回答

37

您的示例代碼應該照原樣運行。假設它是一個自動生成的主鍵列,Sqlalchemy應該爲f.id提供一個值。主鍵屬性在生成時立即在flush()過程中被填充,並且不需要調用commit()。所以這裏的答案在於你的映射的細節,如果後端有任何奇怪的怪癖(例如,SQLite不會爲複合主鍵生成整數值)和/或當你發出SQL時說什麼打開回聲。

+0

你是對的,在shell中快速檢查顯示它用值填充主鍵字段。我將不得不調查爲什麼它在實踐中不起作用。 – Eloff 2009-08-25 06:22:05

+2

「你的示例代碼應該提供一個值」聽起來像你說的「你本應該爲id提供一個值」,而不是「你應該使用的代碼應該保持原樣」。我很清楚,你的意思是後者,而不是在三讀之後。你能澄清嗎? – stochastic 2017-01-08 18:44:39

-7

你應該嘗試使用session.save_or_update(f)代替session.add(f)

+1

'save_or_update'自0.5左右開始不再使用。 'session.add()'應該這樣做。 – 2009-08-23 00:10:47

93

我剛纔遇到同樣的問題,經過測試,我發現沒有任何這些答案是足夠的。

目前,或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. 

這是如何做到這一點。

+6

這越來越接近可能適用於我的答案,但我收到以下錯誤:InvalidRequestError:無法刷新實例'<....>'。在刷新後出現實例不再存在。欣賞任何見解。 – PlaidFan 2011-12-21 04:46:40

+1

你剛剛救了我的屁股。我不認爲我會再次使用來自Django的ORM。 flush()命令不能像記錄的IMHO一樣工作。 – 2016-05-08 21:20:29

+1

更新,我不得不使用'''sessionmaker(autoflush = True)'',組合w/refresh()爲我提供了行ID。 #grrr – 2016-05-08 21:33:13

4

不同於由dpb給出的答案,刷新不是必需的。 一旦你沖洗,你可以訪問id字段,SQLAlchemy的自動刷新它自動在後臺生成

我遇到了這個問題,並想出經過一番調查確切的原因,我的模型與ID創建爲integerfield和ID在我的表單中,id用hiddenfield表示(因爲我不想在表單中顯示id)。隱藏字段默認表示爲文本。一旦我用widget = hiddenInput()將表單更改爲整數字段),問題就解決了。

+1

如前所述,只有refresh()對我有用。在進行數據遷移時,我需要循環中的行ID來填充FK。我試過每一個提交,刷新,會話黑客和刷新()的組合是唯一有效的工作。我的數據超級乾淨,我只是發現SQLA並不是那麼好(在至少5個主要的ORMS中有相當大的exp)。試着獲取add() - > commit()/ flush()的行標識,只需要5+小時的包裝。 – 2016-05-08 21:25:08

1

我曾經在調用session.add方法之前將0分配給了ID,但有一個問題。該ID由數據庫正確分配,但在session.flush()後沒有從會話中檢索到正確的ID。