1

I notice we can set custom image model on wagtail here: https://docs.wagtail.io/en/v2.9/advanced_topics/images/custom_image_model.html

I am trying to add an automated focal point during upload max max 200*220px.

I tried a lot following its above documentation.

from django.db import models

from wagtail.images.models import Image, AbstractImage, AbstractRendition

class CustomImage(AbstractImage):
    # Add any extra fields to image here

    # eg. To add a caption field:
    # caption = models.CharField(max_length=255, blank=True)

    admin_form_fields = Image.admin_form_fields + (
        # Then add the field names here to make them appear in the form:
        # 'caption',
    )


class CustomRendition(AbstractRendition):
    image = models.ForeignKey(CustomImage, on_delete=models.CASCADE, related_name='renditions')

    class Meta:
        unique_together = (
            ('image', 'filter_spec', 'focal_point_key'),

Can anyone please help me get it done setting up custom focal point?

Thanks Anamul

1 Answers1

2

You probably do not need a custom image model to achieve this goal, Django has a built in system called signals. This lets you listen to creation & editing (plus others) of any existing Django model and modify the data before it is saved to the DB.

A good example of this in use already in Wagtail is the feature detection system, which will automatically add a focal point on save if faces are detected.

You can see how this has been implemented in the source code, wagtail/images/signal_handlers.py.

You may need to understand how to build up a focal point, depending on how you want to calculate it but basically you need to call set_focal_point on your image instance. This method must be supplied an instance of a Rect which can be found in the source at images/rect.py.

It is important to understand how to call your signal handlers registration function, I found this Stack Overflow answer to be helpful. However, it might be simpler to just add it to your wagtail_hooks.py file as you know it will be run at the right time (when the app is ready & models are loaded.

You can read more at the Django docs for app.ready() if you would prefer not to rely on the wagtail_hooks.py approach.

Example Implementation

myapp/signal_handlers.py
from django.db.models.signals import pre_save

from wagtail.images import get_image_model
from wagtail.images.rect import Rect


def pre_save_image_add_auto_focal_point(instance, **kwargs):
    # Make sure the image doesn't already have a focal point
    # add any other logic here based on the image about to be saved

    if not instance.has_focal_point():
        # this will run on update and creation, check instance.pk to see if this is new

        # generate a focal_point - via Rect(left, top, right, bottom)
        focal_point = Rect(15, 15, 150, 150)

        # Set the focal point
        instance.set_focal_point(focal_point)


def register_signal_handlers():
    # important: this function must be called at the app ready

    Image = get_image_model()

    pre_save.connect(pre_save_image_add_auto_focal_point, sender=Image)

myapp/wagtail_hooks.py
from .signal_handlers import register_signal_handlers


register_signal_handlers()

LB Ben Johnston
  • 4,751
  • 13
  • 29