如何保存模型,以便不发送信号。 (post_save和pre_save)
答案 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()
here和here,您会发现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
了解更多信息