开发者

Django: base model signal handler doesn't fire

开发者 https://www.devze.com 2023-04-10 03:04 出处:网络
In the following sample code: from django.db import models from django.db.models.signals import pre_save

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.

  1. 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)
    
  2. 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?

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号