How to properly scope validator function in parent class for use in child class

I'm trying to use validators, but I'm having a mysterious issue with using validators in a parent/child class.

Right now I've created a base class for all media in my project; all media in this model need a name and a thumbnail:

class BaseMedia(BaseModel):
    def validate_thumbnail(image_obj):
        validate_image_file_extension(image_obj)
        dimensions = [image_obj.width, image_obj.height]
        if dimensions[0] != 400 or dimensions[1] != 400:
            raise ValidationError(
                "Thumbnail dimensions must be 400 x 400; uploaded image is %s x %s"
                % (dimensions[0], dimensions[1])
            )

    media_title = models.CharField(
        max_length=25, verbose_name="Title (25 char)", null=True
    )
    thumbnail = models.ImageField(
        null=True,
        verbose_name="Thumbnail (400 x 400 px)",
        upload_to="microscopy/images/thumbnails",
        validators=([validate_thumbnail],),
    )

and then I have a child class that inherits and implement the core media itself; for example:

class MicroscopyMedia(BaseMedia):
    def validate_image(image_obj):
        validate_image_file_extension(image_obj)
        dimensions = [image_obj.width, image_obj.height]
        if dimensions[0] != 1920 or dimensions[1] != 1070:
            raise ValidationError(
                "Image dimensions must be 1920 x 1070; uploaded image is %s x %s"
                % (dimensions[0], dimensions[1])
            )

    media = models.ImageField(
        null=True,
        verbose_name="Media (1920 x 1070 px)",
        blank=True,
        upload_to="microscopy/images",
        validators=[validate_image],
    )

The idea being that all models will need a thumbnail, but within the child class I have a specific validator for each individual media type.

However, when I try to make this migration, I get an error:

(env) PS D:\Projects\django-cms\projects\cms> python .\manage.py makemigrations
SystemCheckError: System check identified some issues:

ERRORS:
microscopy.BaseMedia.thumbnail: (fields.E008) All 'validators' must be callable.
        HINT: validators[0] ([<function BaseMedia.validate_thumbnail at 0x000001D3193C8A60>]) isn't a function or instance of a validator class.

There seems to be a scoping issue at play here. As defined, validate_thumbnail() is just a regular function within the scope of BaseMedia, and isn't available to MicroscopyMedia. However, I can't make it a member function either, since I can't pass the self parameter.

How should I define this validator function in the parent class so that when the child class calls it, it's a valid function call?

Structure your code in this way:

def validate_thumbnail(image_obj):
    validate_image_file_extension(image_obj)
    ...

class BaseMedia(BaseModel):
    ...
    thumbnail = models.ImageField(
        ...
        validators=([validate_thumbnail],),
    )

Similarly, promote def validate_image(): so it's up at module scope, rather than buried down within a class definition.

Back to Top