2011-12-06 55 views
0

Ii內SQLAlchemy的定義以下類:SQLAlchemy的映射器事件問題

class User(Base): 
    __tablename__ = 'user' 
    userId = Column(Integer, primary_key=True) 
    email = Column(String(60), unique=True,nullable=False) 
    userName = Column(Unicode(16),unique=True) 
    _password = Column('password', Unicode(60)) 
    groups = relationship("Group",secondary='userGroup') 
    profile = relationship("UserProfile",uselist=False,backref='user') 

class Group(Base): 
     __tablename__ = 'group' 
     groupId = Column(Integer, 
         Sequence('group_id_seq', optional=True), 
         primary_key=True) 
     groupName = Column(Unicode(255), unique=True) 

UserGroupTable = Table('userGroup', Base.metadata, 
     Column('userId', Integer, ForeignKey(User.userId)), 
     Column('groupId', Integer, ForeignKey(Group.groupId)) 
    ) 


class UserProfile(Base): 
    __tablename__='userProfile' 
    userId = Column(Integer, ForeignKey('user.userId'), primary_key=True) 
    dateJoin = Column(Date,nullable=False,default=func.current_date()) 
    gender = Column(Integer) 

user是在一個多到多的關係與group並且當我初始化表中,我加入兩組「用戶」和'admin'如下。問題是,當我使用映射事件添加用戶到「用戶」組時插入,這是行不通的:

def before_insert_user_listener(mapper,connection,target): 
    session=DBSession() 
    ug=session.query(Group).filter(Group.groupName=='user').first() 
    target.groups.append(ug)  
    target.profile=UserProfile() 
    log.debug(">>>>>") 

def initialize_sql(engine): 
    DBSession.configure(bind=engine) 
    Base.metadata.bind = engine 
    Base.metadata.create_all(engine) 
    try: 
     session = DBSession() 
     #event register 
     event.listen(User,'before_insert',before_insert_user_listener) 
     group1 = Group('admin') 
     group2 = Group('user') 
     session.add(group1) 
     session.add(group2)   
     transaction.commit() 
    except IntegrityError: 
     pass 

當我嘗試添加新用戶,該用戶被添加,和我可以看到來自事件偵聽器的日誌打印,但用戶不會添加到「用戶」組。我也嘗試了'after_insert'事件,但它也沒有工作。

編輯:我添加userProfile表,這是一種對用戶的一對一關係,並且用戶配置文件可以使用上面的before_insert事件中的默認連接日期來創建。添加用戶組仍然不工作。

我錯過了什麼?

謝謝!

+0

您是否確實在'transaction.commit()'數據庫中存儲了組?我沒有看到他們被添加到'session'中。 – van

+0

啊..其實他們被添加..我刪除不相關的代碼,並刪除這些錯誤的行。剛剛添加。謝謝指出。 – 3van

+0

我想是的,但請確保測試代碼中的'DBSession()'和事件偵聽器實際上是相同的會話。如果不是這樣 - 你找到了原因,你可以使用'object_session'來獲取偵聽器中正確的一個。 – van

回答

1

如從before_insert文檔提取物表明:

基於列的屬性可以此方法將 結果在新的值被插入內進行修改。不過沒有變化到 可以提出整體刷新計劃,並且操縱會話將會對 沒有期望的效果。要在 擴展中操作會話,請使用SessionExtension。

從中我得出結論:無法向正在提交/刷新或添加/設置關係的會話添加新對象。

我想更好的辦法是聽before_commitbefore_flush會話事件,檢查所有新User對象,並將它們添加到User組。例如:

def my_before_commit(session): 
    g=session.query(Group).filter(Group.groupName=='user').one() 
    for target in session: 
     if isinstance(target, User) and target in session.new: 
      target.groups.append(ug) 
+0

感謝您的回覆麪包車。我剛剛嘗試過before_commit事件。它也不會將用戶添加到「用戶」組。然而奇怪的是我爲用戶表添加的另一個關係,userProfile,與'before_insert'和'after_insert'(我添加到我的帖子上面)。我開始懷疑我的模式設計... – 3van