Удаление объекта из сеанса SQLAlchemy до его сохранения - PullRequest
18 голосов
/ 29 ноября 2011

Мое приложение позволяет пользователям создавать и удалять Site объекты. Я реализовал это, используя session.add() и session.delete(). Затем у меня есть кнопки «Сохранить» и «Сброс», которые вызывают session.commit() и session.rollback().

Если я добавляю новый Site, затем сохраняю / фиксирую его, а затем удаляю, все идет хорошо. Однако, если я пытаюсь удалить объект из сеанса до того, как он будет сохранен, я получаю ошибку «not persisted».

Код:

self.newSite = Site('foo')
self.session.add(self.newSite)
print self.session.new
self.session.delete(self.newSite)

Выход:

IdentitySet([<Site('foo')>])

Traceback (most recent call last):
  File "C:\Program Files\Eclipse\dropins\plugins\org.python.pydev.debug_2.2.1.2011071313\pysrc\pydevd_comm.py", line 744, in doIt
    result = pydevd_vars.evaluateExpression(self.thread_id, self.frame_id, self.expression, self.doExec)
  File "C:\Program Files\Eclipse\dropins\plugins\org.python.pydev.debug_2.2.1.2011071313\pysrc\pydevd_vars.py", line 375, in evaluateExpression
    result = eval(compiled, updated_globals, frame.f_locals)
  File "<string>", line 1, in <module>
  File "C:\Python27\Lib\site-packages\sqlalchemy\orm\session.py", line 1245, in delete
    mapperutil.state_str(state))
InvalidRequestError: Instance '<Site at 0x1ed5fb0>' is not persisted

Я понимаю, что здесь происходит, но я не уверен, что мне следует делать вместо этого.

Есть ли какой-то другой метод удаления еще не сохраненного объекта из сеанса? Или мне следует позвонить session.flush() перед попыткой удаления, если объект, который я хочу удалить, еще не очищен?

Если это последнее, то session.query() автоматически сбрасывается (гарантируя, что ожидающие объекты отображаются в результатах запроса), а session.delete() - нет (что обеспечит возможность удаления отложенных объектов без ошибок)

1 Ответ

15 голосов
/ 29 ноября 2011

Вы можете Session.expunge() это. Я думаю, что логическое обоснование того, что delete() таков, состоит в том, что вас беспокоит, что вы не отследите, если отправите запрос в ожидании. Но я вижу другую сторону этой истории, я подумаю над этим. В основном состояние, подразумеваемое delete(), включает в себя некоторые предположения о постоянстве, но они, вероятно, не так значительны, как я думаю. Затем приходит на ум метод «удалить или удалить», что забавно, в основном это «сохранить или обновить», которое мы изначально скопировали из Hibernate, который просто стал «добавлять». «add» может делать переходы transient-> pending, а также detached-> persistent - будет ли потенциальный «remove ()» одновременно pending-> transient и persistent-> delete? Жаль, что в сеансе с определенными областями уже есть "remove ()" ....

Session.query() автоматически сбрасывается, потому что он собирается выйти в базу данных, чтобы выдать некоторый SQL, чтобы получить несколько строк; поэтому все, что у вас есть, должно выходить на улицу первым. delete() просто отмечает состояние объекта, поэтому нет необходимости вызывать SQL. Если бы мы хотели, чтобы delete() работал над ожиданием, мы бы просто изменили это утверждение.

Интересно, что если вы rollback() сеанс, все, что вы add() редактировали в этом сеансе, независимо от того, был ли он очищен, удаляется.

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