django-polymorphic icon indicating copy to clipboard operation
django-polymorphic copied to clipboard

contribute_to_class issue with specific model inheritance scenarios

Open brocksamson opened this issue 5 years ago • 0 comments

Say we have the following model structure:

class Event(models.PolymorphicModel):
    image = models.ImageField(width_field='image_width', height_field='image_height')
    image_width = models.IntegerField()
    image_height = models.IntegerField()


class UserEvent(Event):
    user = models.ForeignKey('User', on_delete=models.CASCADE)

The image_width and image_height fields will not be correctly filled out when reading a UserEvent (via UserEvent.objects.get or similar) from the db. This is because of how the contribute_to_class method works on the ImageField class. Here is the code for that method:

def contribute_to_class(self, cls, name, **kwargs):
        super().contribute_to_class(cls, name, **kwargs)
        # Attach update_dimension_fields so that dimension fields declared
        # after their corresponding image field don't stay cleared by
        # Model.__init__, see bug #11196.
        # Only run post-initialization dimension update on non-abstract models
        if not cls._meta.abstract:
            signals.post_init.connect(self.update_dimension_fields, sender=cls)

The issue is the sender=cls within the connect. If you inspect cls within this method you find that the contribute_to_class is called for the Event model, but it is not called for the UserEvent model. This results in the post_init signal only being wired for the Event model, not the UserEvent model.

Making Event abstract will cause contribute_to_class to be called for UserEvent, but that isn't what I want.

brocksamson avatar Apr 28 '20 18:04 brocksamson