sqlalchemy映射器事件问题

时间:2011-12-06 14:29:17

标签: python sqlalchemy

Ii在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)

usergroup处于多对多关系中,当我初始化表格时,我添加了两个“用户”和“管理员”组,如下所示。问题是,当我使用mapper事件在插入时将用户添加到“用户”组时,它不起作用:

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事件中的默认联接日期创建用户配置文件。将用户添加到组仍然无法正常工作。

我错过了什么?

谢谢!

1 个答案:

答案 0 :(得分:1)

正如before_insert文档中的摘录所示:

  

可以在此方法中修改基于列的属性   导致插入新值。但是没有变化   可以进行整体刷新计划,并对会话进行操作   没有达到预期的效果。在一个内部操纵Session   扩展,使用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)