Сигнал 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)
хорошего дня!
Мне удалось получить унаследованные приемники сигнала, работающие с @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)