sqlalchemy flush()并插入id?

时间:2009-08-22 20:21:43

标签: python sqlalchemy

我想做这样的事情:

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

7 个答案:

答案 0 :(得分:110)

我遇到了同样的问题,经过测试后我发现没有这些答案就足够了。

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

这是怎么做的。

答案 1 :(得分:52)

您的示例代码应该按原样运行。 Sqlalchemy应该为f.id提供一个值,假设它是一个自动生成的主键列。主键属性在flush()过程中立即填充,因为它们是生成的,并且不需要调用commit()。所以这里的答案在于映射的细节,如果使用后端有任何奇怪的怪癖(例如,SQLite不为复合主键生成整数值)和/或当你发出的SQL所说的内容打开回声。

答案 2 :(得分:9)

谢谢大家。我通过修改列映射解决了我的问题。对我来说,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)

没问题!

答案 3 :(得分:5)

与dpb给出的答案不同,不需要刷新。 一旦刷新,你可以访问id字段,sqlalchemy会自动刷新后端自动生成的id

我遇到了这个问题并且在经过一些调查之后想出了确切的原因,我的模型是用id作为整数字段创建的,在我的形式中,id用hiddenfield表示(因为我不想在我的表单中显示id)。隐藏字段默认表示为文本。一旦我用widget = hiddenInput()将表单更改为integerfield,问题就解决了。

答案 4 :(得分:1)

我曾在调用0方法之前将session.add分配给id时遇到问题。数据库正确分配了id,但在session.flush()之后未从会话中检索到正确的ID。

答案 5 :(得分:0)

我的代码是这样工作的:

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

答案 6 :(得分:-7)

您应该尝试使用session.save_or_update(f)代替session.add(f)