Reputation: 21
Ii defined the following classes in 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)
The user
is in a many-to-many relationship with group
and when I initialised the tables, I added two groups 'user' and 'admin' as below. The problem is that when I use the mapper event to add a user to 'user' group when insert, it does not work:
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
When i try to add a new user, the user is added, and I can see the log print from the event listener, but the user is not added to the 'user' group. I also tried the 'after_insert' event, but it also didn't work.
Edit: I add the userProfile table which is a one-to-one relationship to user,and a user profile can be create with default join date in above before_insert event. add user to group still not working though.
What did I miss?
Thanks!
Upvotes: 0
Views: 1219
Reputation: 77082
As the extract from the before_insert documentation suggests:
Column-based attributes can be modified within this method which will result in the new value being inserted. However no changes to the overall flush plan can be made, and manipulation of the Session will not have the desired effect. To manipulate the Session within an extension, use SessionExtension.
from which I conclude that one cannot add new objects to the session which is being commited/flushed or add/set relationships.
I guess the better way would be to listen to before_commit or before_flush session event, check all new User
objects and adding them to the User
group. For example:
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)
Upvotes: 1