2011-12-06 5 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) 

usergroupと多対多の関係にあり、私はテーブルを初期化するとき、私は2つのグループのユーザー」を追加し、以下のように '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 

、およびI:問題は、私は、インサート、それが動作しない場合「ユーザー」グループにユーザーを追加するマッパーイベントを使用する場合ということですイベントリスナーからのログプリントを見ることができますが、ユーザーは 'user'グループに追加されません。私はまた、 'after_insert'イベントを試みましたが、それはまた動作しませんでした。

編集:ユーザーと1対1の関係であるuserProfileテーブルを追加し、上記のbefore_insertイベントで既定の参加日を使用してユーザープロファイルを作成できます。グループにユーザーを追加してもまだ動作しません。

私は何を欠席しましたか?

ありがとうございます! before_insertドキュメントから抽出物として

+0

実際には、データベースに 'transaction.commit()'のグループを格納しましたか?私はそれらが 'session'に追加されているのを見ません。 – van

+0

ああ。実際には追加されています。私は無関係なコードを削除していて、誤ってそれらの行を削除しました。ちょうど加えられた。指摘してくれてありがとう。 – 3van

+0

私はそうだと思いますが、テストコードとイベントリスナーの 'DBSession()'が実際に同じセッションであることを確認してください。そうでない場合は、理由を見つけたので、 'object_session'を使ってリスナーに適切なものを取得することができます。 – van

答えて

1

が示唆:

列ベースの属性が新しい値に 結果が挿入されます。この方法内で変更することができます。しかし、を に変更しないと、全体的なフラッシュプランを作成することができ、セッションの操作には希望の効果がありません 。拡張子 内のセッションを操作するには、SessionExtensionを使用します。

私は、コミット/フラッシュされているセッションに新しいオブジェクトを追加したり、関係を追加/設定できないと判断しました。

私はより良い方法は、before_commitまたはbefore_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イベントを試しました。ユーザーを 'ユーザー'グループに追加することはありません。しかし、奇妙なことは私がuserテーブルに追加した別の関係、userProfileは 'before_insert'と 'after_insert'で動作します(私は上記の投稿に追加しました)。私は自分のスキーマ設計に疑問を持ち始めています... – 3van