sqlalchemy flush () и получить вставленный идентификатор? - PullRequest
90 голосов
/ 23 августа 2009

Я хочу сделать что-то вроде этого:

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, когда я пытаюсь это сделать. Как я могу заставить это работать?

* 1006 Дан *

Ответы [ 6 ]

110 голосов
/ 22 февраля 2011

Я только что столкнулся с той же проблемой, и после тестирования я обнаружил, что НИКАКОГО из этих ответов не достаточно.

В настоящее время, или в 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.

Вот как это сделать.

53 голосов
/ 25 августа 2009

Ваш пример кода должен работать как есть. Sqlalchemy должен предоставлять значение для f.id, предполагая, что он является автоматически генерирующимся столбцом первичного ключа. атрибуты первичного ключа заполняются непосредственно в процессе flush (), поскольку они генерируются, и не требуется никакого вызова commit (). Таким образом, ответ здесь заключается в деталях вашего отображения, если есть какие-то странные особенности используемого бэкэнда (например, SQLite не генерирует целочисленные значения для составного первичного ключа) и / или что говорит испущенный SQL, когда вы включить эхо.

9 голосов
/ 30 мая 2018

Спасибо всем. Я решил свою проблему, изменив сопоставление столбцов. Для меня autoincrement=True требуется.

Происхождение: id = Column('ID', Integer, primary_key=True, nullable=False)

после изменения: id = Column('ID', Integer, primary_key=True, autoincrement=True, nullable=True)

, то session.flush()<br> print(f.id)

в порядке!

5 голосов
/ 08 октября 2014

в отличие от ответа, данного dpb, обновление не требуется. Как только вы очистите, вы можете получить доступ к полю id, sqlalchemy автоматически обновит идентификатор, который автоматически генерируется на бэкэнде

Я столкнулся с этой проблемой и выяснил точную причину после некоторого исследования, моя модель была создана с идентификатором в качестве целочисленного поля, и в моей форме идентификатор был представлен скрытым полем (так как я не хотел показывать идентификатор в своей форме). Скрытое поле по умолчанию представлено в виде текста. как только я изменил форму на целочисленное поле с widget = hiddenInput ()), проблема была решена.

1 голос
/ 25 февраля 2015

Однажды у меня была проблема с назначением 0 идентификатора перед вызовом session.add метода. Идентификатор был правильно назначен базой данных, но правильный идентификатор не был получен из сеанса после session.flush().

0 голосов
/ 23 августа 2009

Вы должны попробовать использовать session.save_or_update(f) вместо session.add(f).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...