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()
не требуется. Таким образом, ответ здесь заключается в одном или нескольких из следующих:
- Детали вашего отображения
- Если есть какие-то странные особенности используемого бэкэнда (например, SQLite не генерирует целочисленные значения для составного первичного ключа)
- Что говорит испущенный 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)
.