Search code examples
pythondjangodjango-signals

How to use Django model inheritance with signals?


I have a few model inheritance levels in Django:

class WorkAttachment(models.Model):
    """ Abstract class that holds all fields that are required in each attachment """
    work            = models.ForeignKey(Work)
    added           = models.DateTimeField(default=datetime.datetime.now)
    views           = models.IntegerField(default=0)

    class Meta:
        abstract = True


class WorkAttachmentFileBased(WorkAttachment):
    """ Another base class, but for file based attachments """
    description     = models.CharField(max_length=500, blank=True)
    size            = models.IntegerField(verbose_name=_('size in bytes'))

    class Meta:
        abstract = True


class WorkAttachmentPicture(WorkAttachmentFileBased):
    """ Picture attached to work """
    image           = models.ImageField(upload_to='works/images', width_field='width', height_field='height')
    width           = models.IntegerField()
    height          = models.IntegerField()

There are many different models inherited from WorkAttachmentFileBased and WorkAttachment. I want to create a signal, which would update an attachment_count field for parent work, when attachment is created. It would be logical, to think that signal made for parent sender (WorkAttachment) would run for all inherited models too, but it does not. Here is my code:

@receiver(post_save, sender=WorkAttachment, dispatch_uid="att_post_save")
def update_attachment_count_on_save(sender, instance, **kwargs):
    """ Update file count for work when attachment was saved."""
    instance.work.attachment_count += 1
    instance.work.save()

Is there a way to make this signal work for all models inherited from WorkAttachment?

Python 2.7, Django 1.4 pre-alpha

P.S. I've tried one of the solutions I found on the net, but it did not work for me.


Solution

  • You could try something like:

    model_classes = [WorkAttachment, WorkAttachmentFileBased, WorkAttachmentPicture, ...]
    
    def update_attachment_count_on_save(sender, instance, **kwargs):
        instance.work.attachment_count += 1
        instance.work.save()
    
    for model_class in model_classes:
        post_save.connect(update_attachment_count_on_save, 
                          sender=model_class, 
                          dispatch_uid="att_post_save_"+model_class.__name__)
    

    (Disclaimer: I have not tested the above)