如何在不发送信号的情况下保存模型?

时间:2009-10-12 14:56:47

标签: python django django-models

如何保存模型,以便不发送信号。 (post_save和pre_save)

6 个答案:

答案 0 :(得分:40)

这有点像黑客,但你可以这样做:

使用带过滤器的唯一标识符,然后使用查询集的更新方法(不触发信号)

user_id = 142187
User.objects.filter(id=user_id).update(name='tom')

答案 1 :(得分:7)

ticket已标记为“wontfix”,因为:

  

简而言之,听起来,鉴于信号的定义目的,它是   附加的信号处理程序需要变得更加智能   (比如在davedash的建议中),而不是发出的代码   信号。禁用信号只是一个快速解决方案,当你   确切知道哪些处理程序附加到一个信号,它隐藏了   通过将修复程序放在错误的位置来解决潜在的问题。

答案 2 :(得分:1)

目前有一个ticket正在等待此功能的Django设计决定。

故障单中包含一个带有建议实施的补丁的差异。

答案 3 :(得分:1)

据我所知,仍然没有一种“不错”的方法来进行此操作,但是如果您愿意探索hacky解决方案,那么我将添加一个。

如果查看django模型源代码,特别是save_base() herehere,您会发现pre_save()post_save()信号是都包裹在一个条件中:

if not meta.auto_created:
  // Emit signal

我们可以通过_meta API直接操纵模型或实例的元选项,这意味着我们可以通过在auto_created = True上设置@receiver(post_save, sender=(MyModel)) def save_my_model(sender, instance=None, created=False, **kwargs): if created: # Modify the instance instance.task_id = task.task_hash # HACK: Prevent `post_save` signal from being called during save instance._meta.auto_created = True instance.save() instance._meta.auto_created = False elif instance.has_changed("schedule"): # Modify the instance instance.task_id = 'abc123' # HACK: Prevent `post_save` signal from being called during save instance._meta.auto_created = True instance.save() instance._meta.auto_created = False 来“禁用”触发信号。我们要保存的实例。

例如:

id

主要警告是,这是未记录的行为,很可能会改变Django的未来版本。

答案 4 :(得分:0)

如果您在模型及其信号上有相互关系 仍然可以将信号的逻辑解耦以具有更多相同类型的信号,并以更复杂的方式处理逻辑:

您可以检入信号以及对象的状态:

kwargs['created']

您可以检查任何粘贴的附加值的状态: 因此,在一个信号中,您将首先阅读:

if `kwargs['instance'].skip_signals`:
   return

在另一个位置,在save()之前,您将在特定情况下将skip_signals设置在特定对象上。 (无需将其定义为模型字段)

您也可以不发出信号:

  • 通过在模型上覆盖方法
  • 或通过添加自己的save_without_signals()
  • 或如上所述,进行filter(pk=<>).update(...)

答案 5 :(得分:0)

ModelName.objects.bulk_create([your object/objects])

您还可以在这里django docs

了解更多信息