Django: base model signal handler doesn't fire
In the following sample code:
from django.db import models
from django.db.models.signals import pre_save
# Create your models here.
class Parent(models.Model):
name = models.CharField(max_length=64)
def save(self, **kwargs):
print "Parent save..."
super(Parent, self).save(**kwargs)
def pre_save_parent(**kwargs):
print "pre_save_parent"
pre_save.connect(pre_save_parent, Parent)
class Child(Parent):
color = models.CharField(max_length=64)
def save(self, **kwargs):
print "Child save..."
super(Child, self).save(**kwargs)
def pre_save_child(**kwargs):
print "pre_save_child"
pre_save.connect(pre_save_child, Child开发者_如何学编程)
pre_save_parent
doesn't fire when I a Child is created:
child = models.Child.objects.create(color="red")
Is this expected behaviour?
There's an open ticket about this, #9318.
Your workaround looks fine. Here are two others suggested on the ticket by benbest86 and alexr respectively.
Listen on the child class signal, and send the Parent signal there.
def call_parent_pre_save(sender, instance, created, **kwargs): pre_save.send(sender=Parent, instance=Parent.objects.get(id=instance.id), created=created, **kwargs) pre_save.connect(call_parent_pre_save, sender=Child)
Do not specify the sender when connecting the signal, then check for subclasses of parent.
def pre_save_parent(sender, **kwargs): if not isinstance(instance, Parent): return #do normal signal stuff here print "pre_save_parent" pre_save.connect(pre_save_parent)
I didn't realise sender
was an optional parameter to connect
. I can do the following:
def pre_save_handler(**kwargs):
instance = kwargs['instance']
if hasattr(instance, 'pre_save'):
instance.pre_save()
pre_save.connect(pre_save_handler)
This allows me to write per Model pre_save
methods, and they in turn can call any base class versions (if they exists).
Any better solutions?
精彩评论