SQLAlchemy, получить объект, не связанный с сеансом - PullRequest
45 голосов
/ 24 ноября 2011

По разным причинам я пытаюсь получить коллекции объектов из базы данных и передать ее другому процессу, который не связан с базой данных. Мой код похож на приведенный ниже, но я продолжаю получать

sqlalchemy.exc.UnboundExecutionError: Instance <MyClass at 0x8db7fec> is not bound to a Session; attribute refresh operation cannot proceed

Когда я пытаюсь посмотреть на элементы моего списка вне метода get_list().

def get_list (obj):
    sesson = Session()
    lst = session.query(MyClass).all()
    session.close()
    return lst

Однако, если я использую это

def get_list_bis (obj)
    session = Session()
    return session.query(MyClass).all()

Я могу использовать элементы, но беспокоюсь о состоянии сеанса, так как он не был закрыт.

Что мне здесь не хватает?

Ответы [ 3 ]

59 голосов
/ 24 ноября 2011

Если вы хотите, чтобы группа объектов, созданных путем запроса сеанса, могла использоваться вне области сеанса, вам необходимо развернуть их для сеанса.

В первой функцииНапример, вам нужно будет добавить строку:

session.expunge_all()

перед

session.close()

В более общем смысле, скажем, сессия не закрывается сразу, как в первом примере.Возможно, это сеанс, который поддерживается активным в течение всего времени веб-запроса или что-то в этом роде.В таких случаях вы не хотите делать expunge_all.Вы хотите быть более хирургическим:

for item in lst:
    session.expunge(item)
10 голосов
/ 10 мая 2018

Это часто происходит из-за того, что объекты находятся в состоянии expired, срок действия объектов истекает, например, после фиксации , а затем, когда такие просроченные объекты собираются использовать ORM, пытаетсяrefresh их, но этого нельзя сделать, когда объекты отсоединены от сеанса (потому что этот сеанс был, например, закрыт ).Этим поведением можно управлять, создавая сеанс с expire_on_commit=False param.

>>> from sqlalchemy import inspect
>>> insp = inspect(my_object)
>>> insp.expired
True  # then it will be refreshed...
1 голос
/ 06 сентября 2014

В моем случае я также сохранял связанную сущность, и этот рецепт помог мне обновить все экземпляры в сеансе, используя тот факт, что сеанс является итеративным:

map(session.refresh, iter(session))  # call refresh() on every instance

Это крайне неэффективно, но работает. Должно быть хорошо для юнит-тестов.

Последнее замечание: в Python3 map() является генератором и ничего не будет делать. Использовать реальные циклы понимания списка

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