如何使用Flask-SQLAlchemy执行类似post_save信号的Django?

时间:2016-05-04 13:30:26

标签: python flask sqlalchemy flask-sqlalchemy

我想在模型保存时注意,然后进行一些处理并保存另一个模型。我需要模型在处理阶段已经有数据库设置的ID。

使用Django,可以覆盖模型的.save()方法或使用如下信号:

from django.db.models.signals import post_save 
from django.dispatch import receiver

from .models import MyModel, OtherModel

@receiver(post_save, sender=MyModel)
def do_stuff(sender, instance, created, **kwargs):
    assert instance.id is not None
    ...
    OtherModel.create(related=instance, data=...)

如何与SQLAlchemyFlask类似?我查了ORM Events,似乎expire IntanceEvent符合要求。每当模型实例被保存但似乎我尝试做同样的事情时,它似乎会触发:

from sqlalchemy import event

from . import db
from .models import MyModel, OtherModel

@event.listens_for(MyModel, "expire")
def do_stuff(target, attrs):
    assert target.id is not None
    ...
    db.session.add(OtherModel(related=target, data=...))
    db.session.commit()

它在assert instance.id is not None上失败:

InvalidRequestError: This session is in 'committed' state; no further SQL can be emitted within this transaction.

可能是因为我只是以错误的方式接近这一点,或者我错过了一些至关重要但我无法理解的事情。文档分为FlaskFlask-SQLAlchemySQLAlchemy,我很难将它拼凑在一起。

如何使用SQLAlchemy制作此类保存触发器?

2 个答案:

答案 0 :(得分:2)

您想要收听的事件是' after_insert',而不是' expire':

@event.listens_for(MyModel, 'after_insert')
def do_stuff(mapper, connection, target):
    assert target.id is not None
    ...

此外,在侦听器中创建OtherModel并致电db.session.add后,请不要致电db.session.commit,因为它会引发ResourceClosedError例外。

答案 1 :(得分:-1)

查看this question的已接受答案,其中给出了使用SQLAlchemy的after_insert mapper事件的示例。它应该做你想要的,但建议使用原始SQL而不是会话对象。