Skip to content

contribute_to_class issue with specific model inheritance scenarios #431

@brocksamson

Description

@brocksamson

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions