【问题标题】:Django post_save signal on parent class with multi-table inheritance具有多表继承的父类上的Django post_save信号
【发布时间】:2013-01-23 08:58:03
【问题描述】:

在 Django 中,如果您有使用多表继承的模型,并且您为父类上的 post_save 信号定义了接收器,那么在保存子类的实例时是否会调用该接收器函数?

借用一个例子from another question

class Animal(models.Model):
    category = models.CharField(max_length=20)

class Dog(Animal):
    color = models.CharField(max_length=10)

def echo_category(sender, **kwargs):
    print "category: '%s'" % kwargs['instance'].category

post_save.connect(echo_category, sender=Animal)

如果我这样做:

>>> dog = Dog.objects.get(...)
>>> dog.category = "canine"
>>> dog.save()

会调用echo_category 接收函数吗?

【问题讨论】:

    标签: django django-models multi-table-inheritance


    【解决方案1】:

    不,它不会被调用。请参阅 Django 跟踪中的 #9318

    【讨论】:

      【解决方案2】:

      查看: https://code.djangoproject.com/ticket/9318 似乎大多数将信号传播到子类中的超级。

      【讨论】:

        【解决方案3】:
        post_save.connect(my_handler, ParentClass)
        # connect all subclasses of base content item too
        for subclass in ParentClass.__subclasses__():
            post_save.connect(my_handler, subclass)
        

        祝你有美好的一天!

        【讨论】:

        • 你可以把那个 sn-p 安全地放在哪里,这样所有的子类都已经注册了?
        • @ScottStafford 在app ready method
        • 那行不通。应用就绪方法中的子类为空。
        【解决方案4】:

        我设法让继承的信号接收器与 @receiver 装饰器一起工作。 See relevant Django documentation

        from django.db import models
        from django.db.models.signals import post_save
        from django.dispatch import receiver
        
        class Animal(models.Model):
            category = models.CharField(max_length=20)
        
            @receiver(post_save)
            def echo_category(sender, **kwargs):
                print ("category: '%s'" % kwargs['instance'].category)
        
        class Dog(Animal):
            color = models.CharField(max_length=10)
        

        此解决方案在 Python 3.6.8 Django 2.2

        中有效

        当我这样做时

        >>> from myapp.models import Dog
        >>> dog = Dog()
        >>> dog.category = "canine"
        >>> dog.save()
        category: 'canine'
        >>>
        

        没问题。一切似乎都在外壳上工作。


        有点不相关,但是当我通过管理面板编辑模型时,它会被调用两次,所以我通过检查 'created' kwarg 过滤它们。在一个调用中它是假的,另一个是真的,所以我只是放入了一个简单的 if 块。 该解决方法的功劳归于Pratik Mandrekarhis answer

        from django.db import models
        from django.db.models.signals import post_save
        from django.dispatch import receiver
        
        class Animal(models.Model):
            category = models.CharField(max_length=20)
        
            @receiver(post_save)
            def echo_category(sender, **kwargs):
                if not kwargs.get('created'):
                    print ("category: '%s'" % kwargs['instance'].category)
        
        class Dog(Animal):
            color = models.CharField(max_length=10)
        

        【讨论】:

        • 我已经尝试过了,但是每当由于某种原因创建任何模型时,接收器似乎都会被调用
        猜你喜欢
        • 1970-01-01
        • 2019-10-02
        • 1970-01-01
        • 2014-12-18
        • 2011-02-19
        • 2019-03-28
        • 2017-04-26
        • 2012-10-12
        • 1970-01-01
        相关资源
        最近更新 更多