Python SQLAlchemy after_insert 映射事件

2 投票
2 回答
3499 浏览
提问于 2025-04-17 13:41

我刚接触SQLAlchemy,想在创建一个新的用户对象后,默认也创建一个权限对象。看文档说我应该使用after_insert这个事件监听器。问题是,这个事件在对象真正被保存之前就被调用了。

有没有办法让权限对象至少放在一个事务里,或者在用户对象真正保存后再创建的对象列表中呢?

class Users():
  __tablename__ = 'users'
  user_id = Column(String(36), primary_key=True, nullable=False)


class Permissions():
  __tablename__ = 'permissions'
  user_id = Column(String(36), ForeignKey('users.user_id'), primary_key=True,
                   nullable=False)


@event.listens_for(Users, "after_insert")
def create_permissions(mapper, connection, user):
    connection.execute(Permissions.__table__.insert(user_id=user.user_id))

出现了一个错误:IntegrityError: (IntegrityError) (1452, '无法添加或更新子行:外键约束失败')

理想情况下,我希望在用户表上不使用数据库触发器来实现这个功能。

2 个回答

4

你不需要把会话(session)附加到ORM对象上。只需像下面这样使用sqlalchemy.orm模块中的object_session函数:

from sqlalchemy.orm import object_session

@event.listens_for(Users, 'after_insert')
def create_permissions(mapper, connection, user):
    object_session(user).add(Permissions(user_id=user.user_id))
1

通过调整我的类定义,并把会话对象(session object)附加到每个类上,我可以在插入操作完成后添加一个新的权限对象(Permissions object)。这样,正确的提交顺序就能顺利进行。

class Users():
  __tablename__ = 'users'
  user_id = Column(String(36), primary_key=True, nullable=False)
  ............

class Permissions():
  __tablename__ = 'permissions'
  user_id = Column(String(36), ForeignKey('users.user_id'), primary_key=True,
                   nullable=False)
   ............


@event.listens_for(Users, "after_insert")
def create_permissions(mapper, connection, user):
    user.session.add(Permissions(user_id=user.user_id))

撰写回答