2014-01-24 3 views
6

Flask 응용 프로그램 내부의 SQLAlchemy 세션 before_commit 이벤트에 이벤트 수신기를 추가하려고합니다. 다음범위가 지정된 세션의 이벤트 수신기

def before_commit(session): 
    for item in session: 
     if hasattr(item, 'on_save'): 
      item.on_save(session) 

event.listen(db.session, 'before_commit', before_commit) 

을 할 때 나는 이벤트 리스너를 등록 할 수있는 올바른 방법을 찾을 수 없습니다

Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "app.py", line 60, in <module> 
    event.listen(db.session, 'before_commit', before_commit) 
    File "C:\Python27\lib\site-packages\sqlalchemy\event\api.py", line 49, in listen 
    _event_key(target, identifier, fn).listen(*args, **kw) 
    File "C:\Python27\lib\site-packages\sqlalchemy\event\api.py", line 22, in _event_key 
    tgt = evt_cls._accept_with(target) 
    File "C:\Python27\lib\site-packages\sqlalchemy\orm\events.py", line 1142, in _accept_with 
    "Session event listen on a scoped_session " 
sqlalchemy.exc.ArgumentError: Session event listen on a scoped_session requires that its creation callable is associated with the Session class. 

를 얻을. 설명서에 실제로 event.listen()scoped_session을 수락한다고 나와 있지만 그렇지 않은 것 같습니다.

듣는 것은() 함수

http://docs.sqlalchemy.org/en/latest/orm/events.html#sqlalchemy.orm.events.SessionEvents


는 세션 객체뿐만 아니라 sessionmaker()와 scoped_session의 반환 결과를 받아 들일 것입니다().

또한 Session 클래스를 허용하며이 클래스는 모든 세션 인스턴스에 전역 적으로 리스너를 적용합니다.

+1

db.session을 올바르게 설정했는지 확인할 수 있도록 db.session을 설정하는 방법에 대한 코드를 더 게시 할 수 있습니까? 내 생각 엔 db.session 제대로 설정되어 있지 않습니다. – iandouglas

+1

https://github.com/mitsuhiko/flask-sqlalchemy/issues/182 – opyate

+0

을 참조하십시오. 해당 링크에 설명 된 잘 알려진 문제가 발생했습니다. 그러나 여전히 아직 해결되지 않은 것처럼 보입니다. –

답변

4

는 당신이 scoped_session (에 전달했습니다 공장)는 sessionmaker()해야한다는 의미

from sqlalchemy.orm import scoped_session, sessionmaker, sessionmaker 
from sqlalchemy import event 

# good 

ss1 = scoped_session(sessionmaker()) 

@event.listens_for(ss1, "before_flush") 
def evt(*arg, **kw): 
    pass 

# bad 

ss2 = scoped_session(lambda: Session) 

@event.listens_for(ss2, "before_flush") 
def evt(*arg, **kw): 
    pass 
0

는 또 다른 예를 제공하기를,이 코드베이스가 작동하지 않습니다 : https://sourceforge.net/p/turbogears1/code/HEAD/tree/branches/1.5/turbogears/database.py

# good 

class SessionMakerAndBind(sqlalchemy.orm.sessionmaker): 
    def __call__(self, **kw): 
     if not metadata.is_bound(): 
      bind_metadata() 
     return super(SessionMakerAndBind, self).__call__(**kw) 

sessionmaker = SessionMakerAndBind(autoflush=False, 
        autocommit=True, expire_on_commit=False) 
session = sqlalchemy.orm.scoped_session(sessionmaker) 
:
# bad 

def create_session(): 
    """Create a session that uses the engine from thread-local metadata. 

    The session by default does not begin a transaction, and requires that 
    flush() be called explicitly in order to persist results to the database. 

    """ 
    if not metadata.is_bound(): 
     bind_metadata() 
    return sqlalchemy.orm.create_session() 

session = sqlalchemy.orm.scoped_session(create_session) 

대신 그것은 다음과 같은 일을 할 필요가

관련 문제