【问题标题】:Avoiding duplicate signals in Django when editing many_to_many fields编辑 many_to_many 字段时避免 Django 中的重复信号
【发布时间】:2016-03-22 23:47:26
【问题描述】:

我想自动更新有关模型更改的外部应用程序。问题是数据在事件 用户之间存在多对多关系。我尝试使用"m2m_changed" signal

@receiver(m2m_changed, sender=models.Event.organisers.through)
def event_changed(sender, instance, action, *args, **kwargs):
    if "post" in action:
      # hey api here is the new list of organisers of this

这样做的问题是,如果我在删除一个用户并添加另一个用户的地方进行一次更改,那么这段代码会被调用两次!这不好,我不能只忽略一种类型的操作,以防仅调用该操作。我曾想过将实例推送到堆栈并忽略重复,但这似乎很混乱。有没有办法让我自己的信号只触发一次?

【问题讨论】:

  • 你不能让你的代码具有幂等性,这样调用两次就不会造成伤害吗?
  • @LorenzoPeña 那么确保有变化的唯一方法就是询问上述 api。将 api 用于应该是内部功能的东西肯定会增加一些代码债务。如果你有一个聪明的方法,我怎么可以让它被调用两次而不发送 2 个帖子,我全神贯注 :)
  • 尝试dispatch_uid 方法,如docs.djangoproject.com/en/1.9/topics/signals/…中所述
  • @LorenzoPeña 我试过了,但这似乎只有在您的信号连接器运行多次时才能解决问题。
  • 你能负担得起 Django 1.9,其中有一个相关的方法 set() 可以合二为一吗?

标签: python django django-models django-signals


【解决方案1】:

对于这个问题似乎没有很好的答案,所以这里有一些有用的解决方法,它们比我最初想象的要好。

解决方案 1:

而不是组合信号,而是将实例的主键添加到集合中以忽略重复信号:

updated = set()

@receiver(m2m_changed, sender=models.Event.organisers.through) 
def event_changed(sender, instance, action, *args, **kwargs):
        if "post" in action:
          updated.add(instance.pk)

def send_updates():
    for Event in updated:              # Iteration AKA for each element
       #update code here

虽然这需要某种计划任务来运行 send_updates(),但它可以避免在事件有很多连续更改时发送垃圾邮件的机会。

解决方案 2

完全忽略向模型添加最后修改的信号。然后运行查询以获取从现在到上次调用 send_updates() 之间的所有事件。将最后一次调用的内容存储到磁盘/数据库中,以避免在重新启动时重新发送所有内容。

【讨论】:

    【解决方案2】:

    Django m2m_changed 表示对 ManyToMany 模型的更改。如果有 4 个动作

    1. pre_add
    2. post_add
    3. pre_remove
    4. post_remove

    因此,如果您只是添加一个用户,则此 m2m_changed 方法将被触发 2 次,分别为 pre_addpost_add

    您可以指定要在哪个操作处调用 API。这可以这样做:

        @receiver(m2m_changed, sender=models.Event.organisers.through)
        def event_changed(sender, instance, action, *args, **kwargs):
        if kwargs.get('action') == 'pre_add': # Or whatever action you want
           # Call your API here
    

    参考 Django 文档:https://docs.djangoproject.com/en/2.2/ref/signals/#m2m-changed

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-30
      • 2018-10-18
      • 1970-01-01
      • 2019-10-06
      • 2017-09-27
      • 1970-01-01
      • 1970-01-01
      • 2011-03-04
      相关资源
      最近更新 更多