2009-08-30 2 views
6

Я не уверен, как работает scoped_session, кроме того, что это оболочка, которая скрывает несколько реальных сеансов, сохраняя их отдельными для разных запросов. Это делает это с помощью локаторов потоков?Проблемы с scoped_session в sqlalchemy - как это работает?

В любом случае проблема заключается в следующем:

S = elixir.session # = scoped_session(...) 
f = Foo(bar=1) 
S.add(f) # ERROR, f is already attached to session (different session) 

Не знаете, как F оказался в другой сессии, у меня не было проблем с этим раньше. В другом месте у меня есть код, который выглядит именно так, но на самом деле работает. Как вы можете себе представить, я нахожу это очень запутанным.

Я просто ничего не знаю здесь, f, кажется, волшебным образом добавлен в сеанс в конструкторе, но у меня нет ссылок на сеанс, который он использует. Почему это закончилось бы на другой сессии? Как я могу заставить его попасть в правильную сессию? Как эта функция scoped_session работает в любом случае? Кажется, что это работает иногда, а в других случаях просто нет.

Я определенно очень смущен.

ответ

7

Scoped session создает прокси-объект, который хранит реестр (по умолчанию) для объектов сеанса потока, созданных по требованию с фабрики прошедших сеансов. Когда вы получаете доступ к методу сеанса, например ScopedSession.add, он находит сеанс, соответствующий текущему потоку, и возвращает метод add, связанный с этим сеансом. Активный сеанс можно удалить с помощью метода ScopedSession.remove().

ScopedSession имеет несколько удобных методов, один из которых - query_property, который создает свойство, которое возвращает объект запроса, привязанный к сеансу, в котором он был создан, и к классу, к которому он был обращен. Другой - ScopedSession.mapper, который добавляет конструктор по умолчанию __init__(**kwargs) и по умолчанию добавляет созданные объекты в сеанс с привязкой к сеансу, который был сгенерирован. Это поведение можно контролировать с помощью аргумента ключевого слова save_on_init. ScopedSession.mapper устарел из-за проблемы, которая находится в вопросе. Это один из случаев, когда действительно применима философия Python «лучше, чем неявная». К сожалению, Elixir по-прежнему по умолчанию использует ScopedSession.mapper.

2

Оказывается, комплекты эликсиров save-on-init = True на созданных картах. Это может быть отключено:

using_mapper_options(save_on_init=False) 

Решение этой проблемы. Престижность, чтобы зайти на #sqlalchemy для выяснения того, что происходило немедленно. Хотя мне все еще интересно, как scoped_session действительно работает, поэтому, если кто-то ответит на это, они получат кредит на ответ на этот вопрос.

Смежные вопросы