Sqlalchemy flush() и получить вставленный идентификатор?

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

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

Ответ 1

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

  1. Детали вашего отображения
  2. Если есть какие-то странные особенности используемого бэкэнда (например, SQLite не генерирует целочисленные значения для составного первичного ключа)
  3. Что говорит испущенный SQL при включении эха

Ответ 2

Я просто столкнулся с одной и той же проблемой, и после тестирования я обнаружил, что 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.

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

Ответ 3

Спасибо всем. Я решил свою проблему, изменив сопоставление столбцов. Для меня 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)

в порядке!

Ответ 4

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

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

Ответ 5

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

Ответ 6

Попробуйте использовать session.save_or_update(f) вместо session.add(f).