Сигнал Django post_save для родительского класса с наследованием нескольких таблиц

В Django, если у вас есть модели, в которых используется наследование нескольких таблиц, и вы определяете приемник для сигнала post_save в родительском классе, вызывается ли функция получателя при сохранении экземпляра дочернего класса?

Заимствуя пример из другого вопроса:

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 функцию приемника вызывать?

3 ответа

Решение

Проверьте: https://code.djangoproject.com/ticket/9318 Похоже, что большинство распространяют сигнал на супер в подклассе.

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)

хорошего дня!

Нет, это не будет называться. Смотрите #9318 в Django trac.

Мне удалось получить унаследованные приемники сигнала, работающие с @receiver декоратор. Смотрите соответствующую документацию Django

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 Mandrekar за этот обходной путь идет Pratik Mandrekar и его ответу:

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)
Другие вопросы по тегам