django 暂时禁用信号 [英] django temporarily disable signals

查看:56
本文介绍了django 暂时禁用信号的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 Django 中有一个信号回调:

I have a signal callback in django:

@receiver(post_save, sender=MediumCategory)
def update_category_descendants(sender, **kwargs):
    
    def children_for(category):
        return MediumCategory.objects.filter(parent=category)
    
    def do_update_descendants(category):
        children = children_for(category)
        descendants = list() + list(children)
        
        for descendants_part in [do_update_descendants(child) for child in children]:
            descendants += descendants_part
        
        category.descendants.clear()
        for descendant in descendants:
            if category and not (descendant in category.descendants.all()):
                category.descendants.add(descendant)
                category.save()
        return list(descendants)
    
    # call it for update
    do_update_descendants(None)

...但在信号处理程序的主体中,我在同一模型 MediumCategory 上使用了 .save().这会导致再次发送信号.我怎样才能禁用它?

...but in the signal handler's body I'm using .save() on the same model MediumCategory. This causes the signal to be dispatched again. How can I disable it?

完美的解决方案是一个 with 语句,其中包含一些魔法".

The perfect solution would be a with statement with some 'magic' inside.

更新:如果有人感兴趣,这是我的最终解决方案:

UPDATE: Here is my final solution, if anyone interested:

class MediumCategory(models.Model):
    name = models.CharField(max_length=100)
    slug = models.SlugField(blank=True)
    parent = models.ForeignKey('self', blank=True, null=True)
    parameters = models.ManyToManyField(AdvertisementDescriptonParameter, blank=True)
    count_mediums = models.PositiveIntegerField(default=0)
    count_ads = models.PositiveIntegerField(default=0)
    
    descendants = models.ManyToManyField('self', blank=True, null=True)
    
    def save(self, *args, **kwargs):
        self.slug = slugify(self.name)
        super(MediumCategory, self).save(*args, **kwargs)
    
    def __unicode__(self):
        return unicode(self.name)
(...)
@receiver(post_save, sender=MediumCategory)
def update_category_descendants(sender=None, **kwargs):
    def children_for(category):
        return MediumCategory.objects.filter(parent=category)
    
    def do_update_descendants(category):
        children = children_for(category)
        descendants = list() + list(children)
        
        for descendants_part in [do_update_descendants(child) for child in children]:
            descendants += descendants_part
        
        if category:
            category.descendants.clear()
            for descendant in descendants:
                category.descendants.add(descendant)
        return list(descendants)
    
    # call it for update
    do_update_descendants(None)

推荐答案

也许我错了,但我认为您的代码中不需要 category.save(),add() 是足够了,因为更改是在后代中进行的,但在类别中.

Perhaps I'm wrong, but I think that category.save() is not needed in your code, add() is enough because change is made in descendant but in category.

此外,为了避免信号,您可以:

Also, to avoid signals you can:

  • 断开信号并重新连接.
  • 使用更新:Descendant.objects.filter(pk =descendant.pk).update(category = category)
  • Disconnect signal and reconnect.
  • Use update: Descendant.objects.filter( pk = descendant.pk ).update( category = category )

这篇关于django 暂时禁用信号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆