Silver Light Silver Light - 6 months ago 56
Python Question

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.

Answer

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)

Comments