【问题标题】:Django pre_save signal: check if instance is created not updated, does kwargs['created'] (still) exist?Django pre_save 信号:检查实例是否创建未更新,kwargs['created'](仍然)存在吗?
【发布时间】:2010-08-31 09:09:47
【问题描述】:

我正在使用 Django 的 pre_save 信号来实现 auto_now_add。互联网上有很多关于为什么应该或不应该自己实现它的讨论。我不欣赏这方面的cmets。也不是我是否应该重写保存函数(我有很多使用 auto_now_add 的模型,所以使用信号是有意义的)。

我的问题是:
我想检查实例是否已创建或更新。根据互联网上的一些消息来源,这可以通过测试 kwargs['created'] 是否为 True 来完成。但是 'created' 不会出现在我的 kwargs 中,即使该实例是新创建的。 我只是想知道它是否曾经存在过,或者它已经神奇地消失了。 我知道我也可以测试是否设置了kwargs['instance'].id(这实际上对我有用),但我想知道 kwargs['created'] 是否仍然存在。

【问题讨论】:

  • 要记住的一点是,如果设置了实例 id/pk 并不一定意味着该对象存在于数据库中。一个常见的例子是,如果这些实例是从 fixtures 加载的。
  • @Botondus:有没有更好的方法(避免你提到的问题)来检查实例是新创建的还是在 pre_save 期间更新?
  • 是的,如果设置了 PK,您实际上必须查询数据库以确定是否已创建实例。类似于: MyModel.objects.filter(pk=pk_val).exists() 它实际上在 Django 内部以类似的方式实现:code.djangoproject.com/browser/django/trunk/django/db/models/…
  • 感谢您的提示!我已将它包含在我的代码中,并将在以后的项目中记住这一点。

标签: python django keyword-argument


【解决方案1】:

您可以通过这种方式轻松检查在 pre_save 中是否创建或更新了实例:

@receiver(pre_save, sender=MyModel)
def pre_save_user(sender, instance, **kwargs): 
    if instance._state.adding:
        print ('Instance created!')
    else:
        print ('Instance updated!')

使用 Django 3.0 测试。

【讨论】:

    【解决方案2】:

    主键属性通常由数据库在实例第一次保存时分配。所以你可以使用if instance.pk is None

    【讨论】:

    • @phasetwenty 您可以锁定表并额外检查是否存在具有此类自然键的记录。或者使用代理键作为主要和自然次要。
    • 在 Django 中,所有内容都有一个主键,因此这是检查实例是否已保存的一种非常标准的方法。即使是自然键模型也会有一个 pk,您可以检查它以确定实例是否已保存。
    • 这比使用私有方法或属性更可取。
    【解决方案3】:

    根据最新的 Django documentationpre_save 不会发送 created 参数。 Post_save 然而does。由于version 1.0,我找不到任何关于发送created 的信号的参考。

    【讨论】:

    • 非常感谢您的回复。我一定是误读了来源,并假设“创建”也出现在 pre_save 信号中。当你考虑它时,它实际上是有道理的。感谢您为我解决这个问题!
    • 正如 Manoj 所说,在这种情况下,您可以使用 instance.pk 并验证该行是否存在,在这种情况下是更新
    【解决方案4】:

    使用 instance._state.adding 是最合乎逻辑的方法,因为您将能够判断模型状态是否存在,无论主键是否已分配。

    【讨论】:

      【解决方案5】:

      我不确定这是否是推荐的方法,但@Radagast 的方法对我不起作用(不确定是不是因为我使用了自定义 Pk)。

      我尝试了以下方法(不确定这是否是最好的方法):

      @receiver(pre_save, sender=YourModelName, weak=False, )
      def presave_payment_model_check(sender, instance=None, created=False, **kwargs):
          #Reference: https://stackoverflow.com/questions/11561722/django-what-is-the-role-of-modelstate
          if instance._state.adding:
              # we would need to create the object
              print "Creating an object"
          else:
              #we are updating the object
              print "Updating an object"
          
      

      参考:Django : What is the role of ModelState?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-08-17
        • 1970-01-01
        • 1970-01-01
        • 2019-02-26
        • 2011-12-22
        • 2019-09-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多