我想在模型保存时注意,然后进行一些处理并保存另一个模型。我需要模型在处理阶段已经有数据库设置的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=...)
如何与SQLAlchemy
和Flask
类似?我查了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.
可能是因为我只是以错误的方式接近这一点,或者我错过了一些至关重要但我无法理解的事情。文档分为Flask
,Flask-SQLAlchemy
和SQLAlchemy
,我很难将它拼凑在一起。
如何使用SQLAlchemy
制作此类保存触发器?
答案 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而不是会话对象。