是否可以在 SQLAlchemy 中创建一个可以创建父记录的事件侦听器?

2024-05-02

有两个表:父表和子表。我想创建一个事件监听器(“触发器”),如果孩子没有父母,它可以创建父母。

这就是我试图做的:

class parent(db.Model):
    __tablename__ = 'parent'
    id = db.Column(db.Integer, primary_key=True)
    children = db.relationship("child", backref="parent",
                               cascade="all, delete-orphan",
                               passive_deletes=True)


class child(db.Model):
    __tablename__ = 'child'
    id = db.Column(db.Integer, primary_key=True)
    parent_id = db.Column(db.Integer,
                          db.ForeignKey('parent.id', ondelete='CASCADE'),
                          nullable=False)


def create_parent(mapper, connection, target):
    if not(target.parent):
         target.parent = parent()

event.listen(child, 'before_insert', create_parent)     

Test:

c = child()
db.session.add(c)
db.session.commit()

并收到以下警告和错误:

C:\Python27\x\lib\site-packages\sqlalchemy\orm\unitofwork.py:79: SAWarning: Usage of the 'related attribute set' operation is not currently supported within the execution stage of the flush process. Results may not be consistent.  Consider using alternative event listeners or connection-level operations instead.
  sess._flush_warning("related attribute set")

C:\Python27\x\lib\site-packages\sqlalchemy\orm\unitofwork.py:37: SAWarning: Usage of the 'collection append' operation is not currently supported within the execution stage of the flush process. Results may not be consistent.  Consider using alternative event listeners or connection-level operations instead.
  sess._flush_warning("collection append")

sqlalchemy.exc.IntegrityError: (IntegrityError) null value in column "parent_id" violates not-null constraint
DETAIL:  Failing row contains (1, null).
 'INSERT INTO child (parent_id) VALUES (%(parent_id)s) RETURNING child.id' {'parent_id': None}

我在文档中发现这不能通过 before_insert 事件来实现,而是通过 before_flush 来实现,但我不知道如何做到这一点。


与此同时,我找到了解决这个问题的方法。

from sqlalchemy.orm.session import Session as SessionBase

def before_flush(session, flush_context, instances):
    children = [c for c in session.new if isinstance(c, child)]
    for c in children:
        if not (c.parent):
            c.parent = parent()

event.listen(SessionBase, "before_flush", before_flush)

如果有人发现这不是处理这种情况的正确方法,我将感谢您的评论。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

是否可以在 SQLAlchemy 中创建一个可以创建父记录的事件侦听器? 的相关文章

随机推荐