33

我看到pre_save, save, post_save当模型实例被保存时,我可以覆盖或定义做我想做的事情。

在哪种情况下首选哪一种,为什么?

4

3 回答 3

36

我将尽力用一个例子来解释它:

pre_savepost_save是模型发送的信号简而言之,save调用模型之前或之后要采取的行动。

Asave 触发以下步骤

  • 发出预存信号。
  • 预处理数据。
  • 大多数字段不进行预处理——字段数据保持原样。
  • 为数据库准备数据。
  • 将数据插入数据库。
  • 发出保存后信号。

Django 确实提供了一种方法来覆盖这些信号。

现在,

pre_save在实际保存到数据库之前,可以覆盖信号以进行某些处理 - 示例:(我不知道一个很好的例子,说明哪里pre_save最适合我的头脑)

假设您有一个ModelA存储对尚未编辑的所有对象ModelB引用。为此,您可以在's方法被调用之前注册一个信号来通知(没有什么能阻止您在这里注册一个信号)。pre_saveModelAModelBsavepost_save

现在,save调用模型的方法(它不是信号) - 默认情况下,每个模型都有一个save方法,但您可以覆盖它:

class ModelB(models.Model):
    def save(self):
        #do some custom processing here: Example: convert Image resolution to a normalized value
        super(ModelB, self).save()

然后,就可以注册post_save信号了(这个用的比较多pre_save

一个常见的用例是在系统中创建UserProfile对象时创建User对象。

您可以注册一个post_save信号,该信号创建一个UserProfile对应User于系统中每个的对象。

信号是一种保持事物模块化和明确的方式。(明确通知ModelAsave或更改某些内容ModelB

为了更好地回答这个问题,我将考虑更具体的现实世界示例。同时,我希望这对你有帮助

于 2013-07-15T15:38:33.280 回答
5

不要忘记递归风险。如果您使用带有instance.save()调用的post_save方法,而不是 .update 方法,您应该断开您的post_save信号:

Signal.disconnect(receiver=None, sender=None, dispatch_uid=None)[source] 要断开接收器与信号的连接,请调用 Signal.disconnect()。参数如 Signal.connect() 中所述。如果接收器断开连接,则该方法返回 True,否则返回 False。

接收器参数指示注册的接收器断开连接。如果 dispatch_uid 用于识别接收者,它可能是 None。

...然后再次连接。

update()方法不发送 pre_ 和 post_ 信号,请记住这一点。

于 2016-10-06T10:03:50.120 回答
3
pre_save

它在事务保存之前使用。

post_save

它在事务保存后使用。

pre_save例如,您可以使用aFileField或 anImageField 并查看 thefile或 the是否image真的存在。

post_save当你有一个UserProfile并且你想在创建一个新的时创建一个新的时,你可以使用User它。

于 2013-07-15T02:19:14.227 回答