首页 > 解决方案 > Peewee 我如何为依赖项调用 post_delete 信号?

问题描述

我看到 peewee 有信号http://docs.peewee-orm.com/en/latest/peewee/playhouse.html#signals

但它仅适用于delete_instance().

由于我希望是显而易见的原因,当您使用 Model.insert()、Model.update() 或 Model.delete() 方法时,Peewee 信号不起作用。这些方法会生成超出 ORM 范围执行的查询,并且 ORM 不知道在查询执行时哪些模型实例可能会或可能不会受到影响。

信号通过连接到更高级别的 peewee API 来工作,例如 Model.save() 和 Model.delete_instance(),其中受影响的模型实例是提前知道的。

那么,我如何在依赖关系的记录上使用信号,因为它使用delete()依赖关系?

def delete_instance(self, recursive=False, delete_nullable=False):
        if recursive:
            dependencies = self.dependencies(delete_nullable)
            for query, fk in reversed(list(dependencies)):
                model = fk.model
                if fk.null and not delete_nullable:
                    model.update(**{fk.name: None}).where(query).execute()
                else:
                    model.delete().where(query).execute()
        return type(self).delete().where(self._pk_expr()).execute()

标签: foreign-keyshookpeeweecascading-deletes

解决方案


简短的回答是你不能,因为递归删除是使用以下形式的查询实现的:

DELETE FROM ... WHERE foreign_key_id = X

例如,假设您有一个用户,他们创建了 1000 条推文。tweet.user_id 指向 user.id。当您删除该用户时,peewee 会发出 2 个查询:

DELETE FROM tweets WHERE user_id = 123
DELETE FROM users WHERE id = 123

如果它打电话给delete_instance()你,你最终会发出 1001 个查询。因此,希望很清楚为什么以这种方式实施它。

我建议,如果您要删除行并且需要对相关行执行某种清理,那么您最好进行软删除(例如,设置 a status=DELETED)。然后处理信号 API 之外的任何关系。


推荐阅读