【问题标题】:when to use pre_save, save, post_save in django?何时在 django 中使用 pre_save、save、post_save?
【发布时间】:2013-07-12 19:39:53
【问题描述】:

我知道我可以覆盖或定义 pre_save, save, post_save 以在保存模型实例时执行我想要的操作。

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

【问题讨论】:

    标签: python django django-models django-signals


    【解决方案1】:

    我尽量举例说明:

    pre_savepost_save 是模型发送的signals。简单来说,就是在模型的save 之前或之后采取的行动被调用。

    一个savetriggers the following steps

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

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

    现在,

    pre_save 信号可以在实际保存到数据库之前被覆盖以进行某些处理 - 示例:(我不知道pre_save 最适合我的最佳示例)

    假设您有一个ModelA,它存储对ModelB 的所有对象的引用,这些对象尚未被编辑。为此,您可以在调用ModelBsave 方法之前注册pre_save 信号以通知ModelA(也没有什么能阻止您在这里注册post_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用的多)

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

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

    信号是一种保持模块化和明确的方式。 (如果我 save 或更改 ModelB 中的某些内容,请明确通知 ModelA

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

    【讨论】:

    • 感谢您的详细回答。之所以使用post_save 创建UserProfile 是因为可以在post_save 中检查实例是否为created?(而不是在pre_save 中,保存)
    • 您可能想补充一下 pre_save 或 post_save 本身与事务无关的答案。如果您使用 get_or_create 或请求级事务,post_save 将发生在事务内部,而不是在它之后。根据数据库,您可以使用一些 post_commit 信号实现。
    【解决方案2】:

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

    Signal.disconnect(接收方=无,发送方=无, dispatch_uid=None)[source] 断开接收器与信号的连接, 调用 Signal.disconnect()。论据如中所述 信号连接()。如果接收器是,该方法返回 True 如果没有断开连接,则为 False。

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

    ...然后再次连接。

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

    【讨论】:

      【解决方案3】:
      pre_save
      

      在事务保存之前使用。

      post_save
      

      事务保存后使用。

      您可以使用pre_save,例如,如果您有FileFieldImageField,并查看fileimage 是否真的存在。

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

      【讨论】:

      • 对于您的pre_save 示例,您提供了一个检查文件是否存在的示例,使用信号或覆盖保存方法哪个更好?因为如果我在pre_save 信号中添加验证,我会遇到向我的表单提出错误的问题。
      • @Keda87 如果你使用表单,我会去覆盖表单的验证功能。
      • 不! post_save 通常在原子块中调用。这意味着 post_save 发生在交易内部
      猜你喜欢
      • 1970-01-01
      • 2013-07-14
      • 2011-05-30
      • 1970-01-01
      • 2017-04-26
      • 2020-04-08
      • 2018-08-09
      • 2014-03-16
      • 2010-11-16
      相关资源
      最近更新 更多